I'm stuck with strange behavior while migrating my project to kotlin.
It's occurred while i tried to generate dagger injectors. The problem in java or dagger, someone can't resolve kotlin List from generic type
Example:
interface CacheEntity<Result> {
fun onResult(result: Result)
fun getUpdatableData(): Observable<Result>
}
class CacheRepository< Result, Entity:CacheEntity<Result> >(
val entity: Entity) {
// do some operations with Entity
fun doSome() {
entity.getUpdatableData()
entity.onResult(...)
}
}
class UserRepository: CacheEntity<User> {
override fun onResult(result: User) {}
override fun getUpdatableData(): Observable<User> {}
}
Now if i'm tring to create cached user repository instance, everything it's ok Then this code translates to application using dagger injections
val cachedUserRepo = CacheRepository<User, UserRepository>(UserRepository())
But! If i'm trying to result the list of data
class OrdersRepository: CacheEntity<List<Order>> {
// overrides CacheEntity methods
}
val cachedOrdersRepo = CacheRepository<List<Order>, OrdersRepository>(OrdersRepository())
Everything is fine, but not in dagger-generated java code: MyComponent.java
private CacheRepository<List<Order>, OrdersRepository> cachedOrdersRepository;
error while building
error: type argument OrdersRepository is not within bounds of type-variable Entity
private Provider<CachedRepository<List<Order>, OrdersRepository>> cachedOrdersRepository;
^
where Entity,Result are type-variables:
Entity extends CacheEntity<Result> declared in class CacheRepository
Result extends Object declared in class CacheRepository
Java code contains java.util.List which is incompatible with kotlin.collections.List, but dagger module class written in kotlin and returns valid kotlin kotlin.collections.List
@Module
object RepoModule {
@JvmStatic
@Provides
fun provideCacheOrdersRepository(): CacheRepository<List<Order>, OrdersRepository> {
return CacheRepository(OrdersRepository())
}
}
So, how to solve this? I have a couple ideas, but i don't like this:
Rewrite dagger module in java, it worked before i converted to kotlin
Forced using java.util.List, but it's a very bad idea
This is related to the bytecode conversion of a Kotlin list and the wildcards added in the signature, making it a java.util.List<? extends T>
instead of a java.lang.List<T>
.
To fix it without switching to an invariant type (e.g. MutableList
) you should use @JvmSuppressWildcards
on the the List
type:
e.g.
class OrdersRepository: CacheEntity<List<@JvmSuppressWildcards Order>>
I've added just one fragment of your full code, you should check your list usages and use @JvmSuppressWildcards
on them.