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 factories suppress wildcards, but Dagger doesn't #581

Closed
hannesstruss opened this issue Mar 28, 2022 · 2 comments
Closed

Generated factories suppress wildcards, but Dagger doesn't #581

hannesstruss opened this issue Mar 28, 2022 · 2 comments
Labels
bug Something isn't working dagger factory Happens when generateDaggerFactories is set to true

Comments

@hannesstruss
Copy link

Given:

class MyAnvilPresenter @Inject constructor(
  private val getThing: () -> MyThing
)

Anvil will generate this factory:

public class MyAnvilPresenter_Factory(
  private val getThing: Provider<@JvmSuppressWildcards () -> MyThing>
) : Factory<MyAnvilPresenter> {
  public override fun `get`(): MyAnvilPresenter = newInstance(getThing.get())

  public companion object {
    @JvmStatic
    public fun create(getThing: Provider<@JvmSuppressWildcards () -> MyThing>):
        MyAnvilPresenter_Factory = MyAnvilPresenter_Factory(getThing)

    @JvmStatic
    public fun newInstance(getThing: @JvmSuppressWildcards () -> MyThing): MyAnvilPresenter =
        MyAnvilPresenter(getThing)
  }
}

Translated to Java, the type of Provider<@JvmSuppressWildcards () -> MyThing> is Provider<Function0<MyThing>>.

If we would let Dagger generate the factory, it would look like this:

public final class MyAnvilPresenter_Factory implements Factory<MyAnvilPresenter> {
  private final Provider<Function0<? extends MyThing>> getThingProvider;

  public MyAnvilPresenter_Factory(Provider<Function0<? extends MyThing>> getThingProvider) {
    this.getThingProvider = getThingProvider;
  }

  @Override
  public MyAnvilPresenter get() {
    return newInstance(getThingProvider.get());
  }

  public static MyAnvilPresenter_Factory create(
      Provider<Function0<? extends MyThing>> getThingProvider) {
    return new MyAnvilPresenter_Factory(getThingProvider);
  }

  public static MyAnvilPresenter newInstance(Function0<? extends MyThing> getThing) {
    return new MyAnvilPresenter(getThing);
  }
}

This will clash in a project with both Anvil and Dagger modules, as in one dependency graph () -> MyThing can either be provided with or without wildcards, but not both.

Sample project

https://github.com/hannesstruss/anvil-wildcards

@vRallev vRallev added bug Something isn't working dagger factory Happens when generateDaggerFactories is set to true labels Mar 28, 2022
@vRallev
Copy link
Collaborator

vRallev commented Jul 26, 2022

I'm sorry it took me so long, but this is actually a normal Dagger / Java / Kotlin interop issue, see also here.

I looked at your sample and with some smaller tweaks it compiles. First, your provider method should NOT use @JvmWildcard, it should look like this:

fun provideGetThing(): () -> MyThing

When you inject the lambda, then you need to use @JvmSuppressWildcards, e.g.

private val getThing: @JvmSuppressWildcards () -> MyThing

If you change both presenters, then your project compiles.

@vRallev vRallev closed this as completed Jul 26, 2022
@hannesstruss
Copy link
Author

Yep, that works – It's a bit of an issue for us to fix this in a rather large codebase 😅 But as far as I understand, changing this in Anvil would be a breaking change, so I'm not 100% clear on what the solution could be.

Thanks so much for looking into this! 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working dagger factory Happens when generateDaggerFactories is set to true
Projects
None yet
Development

No branches or pull requests

2 participants