I’m facing a compilation issue with the following Kotlin code:
fun interface Producer<out R> {
fun produce(): R
fun <T> T.invokeConsumers(
vararg consumers: Consumer<
R /*Type parameter R is declared as 'out' but occurs in 'in' position in type User<R, Producer<R>>*/,
Producer<R>
>
): List<R> =
consumers.map {
it.consume(this@Producer)
}
}
fun interface Consumer<out R, in P : Producer<R>> {
fun consume(p: P): R
}
I am getting compilation error Type parameter R is declared as 'out' but occurs in 'in' position in type User<R, Producer<R>>, but R is in out position in both interfaces.
Why doesn’t it compile?
Also I would like to leave invokeConsumers function declaration as it is - inside the Producer interface, as an extension for generic type T
This code is a simplification of what I would like to use in my validation library. Won’t this cause problems in the future?
Also thank you for your response!
interface ListConsumer<out T> {
fun consume(list: List<T>) // Type parameter T is declared as 'out' but occurs in 'in' position in type List<T>
}
The compiler message is a bit unclear.
This does not work, because covariant type T is being used in in position - it is used in list function argument, which is not allowed
Function arguments are on example of in position (the object will receive an instance, thus in, opposite of a return type, where an object produces an instance, thus out).
The compiler is right. You will meet an CCE (ClassCastException) in the following case.
interface ListConsumer<out T> {
fun consume(list: List<@UnsafeVariance T>)
}
class ChildConsumer: ListConsumer<Child> {
override fun consume(list: List<Child>) {
val child = list[0]
println(child.c)
}
}
open class Parent
class Child: Parent() {
val c = 1
}
fun main() {
val c: ListConsumer<Parent> = ChildConsumer()
c.consume(listOf(Parent()))
}