Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generated component error. Rawtype provider vs generic MembersInjector #939

Closed
kotucz opened this issue Nov 7, 2017 · 7 comments
Closed

Comments

@kotucz
Copy link

kotucz commented Nov 7, 2017

Generated Dagger component DaggerComp.java cannot be compiled, because of this error:

...\di\DaggerComp.java
Error:(41, 26) error: method injectP in class AFrag_MembersInjector<P#2> cannot be applied to given types;
required: Object,P#1
found: Frag,Object
reason: inferred type does not conform to upper bound(s)
inferred: Object
upper bound(s): APres
where P#1,P#2 are type-variables:
P#1 extends APres declared in method <P#1>injectP(Object,P#1)
P#2 extends APres declared in class AFrag_MembersInjector

Happens using dagger 2.12. Did not occur in previous versions of dagger (2.11 and earlier)
Using AndroidStudio 3.0, Android plugin 3.0.0, Java 8

This issue can be reproduced with following example code:

di/Comp.java

package di;

@Singleton
@Component
interface Comp {
    void inject(Frag f);
}

Frag.java

public class Frag extends AFrag<Pres> {
    @Inject
    Frag() {
    }
}

abstract class AFrag<P extends APres> {
    @Inject
    P p;
}

@Singleton
class Pres extends APres {
    @Inject
    Pres() {
    }
}

abstract class APres {
}

Comp and Pres must be in different package and Pres is not public

Here is the generated DaggerComp.java:

public final class DaggerComp implements Comp {
  @SuppressWarnings("rawtypes")
  private Provider presProvider;

  private DaggerComp(Builder builder) {
    initialize(builder);
  }

  public static Builder builder() {
    return new Builder();
  }

  public static Comp create() {
    return new Builder().build();
  }

  @SuppressWarnings("unchecked")
  private void initialize(final Builder builder) {
    this.presProvider = DoubleCheck.provider(Pres_Factory.create());
  }

  @Override
  public void inject(Frag f) {
    injectFrag(f);
  }

  private Frag injectFrag(Frag instance) {
    AFrag_MembersInjector.injectP(instance, presProvider.get()); // <<< ERROR
    return instance;
  }

  public static final class Builder {
    private Builder() {}

    public Comp build() {
      return new DaggerComp(this);
    }
  }
}
@kotucz
Copy link
Author

kotucz commented Nov 10, 2017

Issue persists in Dagger 2.13

@ultraon
Copy link

ultraon commented Nov 17, 2017

I have the same issue but with Dagger2 version 2.13, with 2.12 - everything alright

@ronshapiro
Copy link

Is this the same as #949?

@kotucz
Copy link
Author

kotucz commented Dec 29, 2017

I do not think that this is caused by compiler. The generated code has mismatch between the required parameter of injectP method and provided argument.

@MartinMMS
Copy link

MartinMMS commented Feb 22, 2018

The problem is that since Dagger 2.12 you cannot do a member injection of a package private type which resides in another package than the main package of the application.
The reason is that the injection code is generated in the DaggerComp which is placed in the main package of the application and therefor has no access to the package private type in another package one want's to inject. This causes the Provider within DaggerComp to be generated as rawtype and the provider.get() method will only return the type Object. The static AFrag_MembersInjector.injectP()-Method cannot handle type Object, because it expects the specific type of P.

So... the simplest solution would be, when Dagger2 would generate a different (or a second) MemberInjector static inject method. So that it does not expect the specific type of P but instead a Provider<P>.

The Function call in DaggerComponent needs to change from
AFrag_MembersInjector.injectP(instance, presProvider.get());
to
AFrag_MembersInjector.injectP(instance, presProvider);
and the MemberInjector should call provider.get() internally.

This would trick the compiler because the raw provider would become a typed provider when given to the static inject method before provider.get() is called. The trick is the same as it already was in Dagger 2.11.

It would be nice if you could change this in an upcoming Dagger2 release but in the meanwhile the only workaround is to not try to inject package private types into other classes via member injection or setter-method injection.

@ronshapiro
Copy link

Are you able to create a Minimal, Complete, and Verifiable example that exhibits this behavior?

Is this still an issue in 2.23.1?

@bcorso
Copy link

bcorso commented Jul 28, 2020

Closing this, since there hasn't been a response in over a year.

Please open back up if you can provide a Minimal, Complete, and Verifiable example of the issue.

@bcorso bcorso closed this as completed Jul 28, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants