I have the following SSCCE:
class Foo(val bars: Map<Int, Bar<*>>) {
fun <Baz> qux(baz: Baz) {
val bar2 = bars[2]!!
bar2.bazes += baz
}
interface Bar<Baz> {
var bazes: MutableList<Baz>
}
}
This seems fine to me, but the compiler complains that:
Error:(5, 9) Kotlin: Setter for 'bazes' is removed by type projection
I have no idea what this even means, much less how to correct it. What's going on here and how do I get around it?
There's a couple little issues. Temporarily using bars[2]!! as Bar<Baz>
,
w: (4, 20): Unchecked cast: Foo.Bar<Any?> to Foo.Bar<Baz>
e: (5, 20): Assignment operators ambiguity:
public operator fun <T> Collection<Baz>.plus(element: Baz): List<Baz> defined in kotlin.collections
@InlineOnly public operator inline fun <T> MutableCollection<in Baz>.plusAssign(element: Baz): Unit defined in kotlin.collections
Kotlin doesn't know whether to handle it as bar2.bazes = bar2.bazes.plus(baz)
or bar2.bazes.plusAssign(baz)
. If you change it to var2.bazes.add(baz)
or val bazes
the ambiguity goes away.
Fixing that and removing the unsafe cast brings up
e: (5, 20): Out-projected type 'MutableList<out Any?>' prohibits the use of 'public abstract fun add(element: E): Boolean defined in kotlin.collections.MutableList'
the question of what can safely be done with the type projection. It gets treated like out Any?
, so you can read from the list, but in Nothing
, which means you can't add anything to the list.
It's unclear from this example why you're using *
. If it doesn't cause any other issues, perhaps you could lift out the <Baz>
parameter, e.g.
class Foo<Baz>(val bars: Map<Int, Bar<Baz>>)