49

I have the following snippet in my dagger 2 module

@Singleton
@Provides
@ElementsIntoSet
fun providesQueries(foo: Foo): Set<Foo>{
    val queries = LinkedHashSet<Foo>()
    queries.add(foo)
    return queries
}

I try to inject into in this way

@Inject lateinit var foo: Set<Foo>

But dagger shows an error which says that Dagger cannot provides java.util.Set without @Provides or @Produces method.

I did the same in java and it worked. Does somebody know why is it failing?

Borja
  • 1,318
  • 13
  • 18
  • What annotation processor do you use? – azizbekian Mar 31 '17 at 14:12
  • I use kapt. I have the following lines in my build.gradle. kapt "com.google.dagger:dagger-compiler:$dagger_version" kapt { generateStubs = true } – Borja Mar 31 '17 at 14:20
  • Compare java generated classes and kotlin generated classes, see the diff. Obviously generated class misses @Produces. – azizbekian Mar 31 '17 at 14:22
  • 2
    No, the problem is that kapt fails into the translation and adds extends Foo> and dagger does not know how to manage that. I'm trying to have this module in java as a workarround. – Borja Mar 31 '17 at 14:25

1 Answers1

108

As it described in the Kotlin reference

To make Kotlin APIs work in Java we generate Box<Super> as Box<? extends Super> for covariantly defined Box (or Foo<? super Bar> for contravariantly defined Foo) when it appears as a parameter.

You can use @JvmSuppressWildcards for avoiding it, just as following:

@Inject lateinit var foo: Set<@JvmSuppressWildcards Foo>
Aleksandr
  • 1,136
  • 1
  • 8
  • 10
  • 4
    MutableSet<> could also be used – Borja Apr 03 '17 at 09:19
  • 22
    Jesus Christ, 2 wasted days! Why it's so painful... Thank you! If anyone like me is struggling with multibinding `Map` it's pretty much the same trick. Ex: `class MviViewModelFactory @Inject constructor(private val providers: Map, @JvmSuppressWildcards Provider>) : ViewModelProvider.Factory {` – Ghedeon Mar 12 '18 at 14:36
  • 1
    Thank you for the answer, I would make some important addition, if you use a specific Qualifier, you have to put "field" in the annotation: "@field:MyQualifier". You don't need to do it if you use Dagger 2.25.2 version and above, AFAIK. – ultraon Nov 05 '19 at 15:48