Status: Accepted
Owner: sberlin

New issue 632 by sberlin: AssistedInject fails with optimized providers in edge cases
http://code.google.com/p/google-guice/issues/detail?id=632

Normally, FactoryProvider2 would expect that the parent inject is constructing 'Object3' here, but Guice will recognize it has a dependency on something only the child can provide, so will fall back into adding the JIT binding for 'Object3' in the child injector. The rest of the FactoryProvider2 didn't expect this, and fails (visible with the "this should never happen").

A fix may be to inspect the JIT bindings of the child injector for dependencies that could invalidate the optimization. (If any child JIT binding exists, it has to be because it depends on an @Assisted param, which means they're tainted too, and all classes need to be analyzed for Provider<..> dependencies on them, and they need to be analyzed for Provider<..> dependencies of other tainted things.)

Test-code
-----

public class GuiceErrorTest extends TestCase {

  @Inject
  Object1Factory object1Factory;

  public void testInjectionFailure() throws Exception  {

    Guice.createInjector(new Module()).injectMembers(this);
    object1Factory.create(1).run();
  }

  public static class Module extends AbstractModule {
    @Override
    protected void configure() {
      install(new FactoryModuleBuilder().build(Object1Factory.class));
      install(new FactoryModuleBuilder().build(Object2Factory.class));
    }
  }

  public interface Object1Factory {
    Object1 create(@Assisted("a1") long a);
  }

  public static class Object1{

    private final Object2Factory object2Factory;
    private final long a;

    @Inject
    public Object1(@Assisted("a1") long a, Object2Factory object2Factory) {
      this.a = a;
      this.object2Factory = object2Factory;
    }

    public void run() throws Exception  {
      object2Factory.create(a).run();
    }
  }

  public interface Object2Factory {
    Object2 create(@Assisted("a1") long a);
  }
  public static class Object2 {
    Provider<Object3> object3Provider;

    @Inject
    public Object2(Provider<Object3> object3Provider) {
      this.object3Provider = object3Provider;
    }

    public void run() {
      object3Provider.get(); // This will fail with an IllegalStateException
    }
  }

  /*
   * Instantiation of this Object fails at runtime:
* Cannot use optimized @Assisted provider outside the scope of the constructor.
   */
  public static class Object3 {

    @Inject
    public Object3(@Assisted("a1") long a) {
    }
  }
}


--
You received this message because you are subscribed to the Google Groups 
"google-guice-dev" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/google-guice-dev?hl=en.

Reply via email to