Modify an element of array

I am trying a code snippet on modifying of an element of an array, and it does seem to work. I get a “Type mismatch” error(squiggly red line) on the line "things[0] = “zero”.
(line before: val things = arrayOf(1,2,3,“one”,“two”,“three”))
According to kotlin help, it should work. What have I done wrong?

Confirmed in the REPL:

>>> val things = arrayOf(1, 2, 3, "one", "two", "three")
>>> things[0] = "zero"
error: type mismatch: inferred type is String but Nothing was expected
things[0] = "zero"
            ^

(It’s not specific to arrays; you get the same issue with mutableListOf().)

The immediate cause is that the inferred type of things is Array<out Any>.⠀Because that’s covariant, it could refer to an array of Any, or of any subtype of Any.⠀So there’s no value that’s safe to write to it.⠀(The type Nothing has no values, which is why that’s expected.)

But I must be half-asleep, because I can’t see why it’s inferring an out type…⠀(It does so even if you specify arrayOf<Any>(…)!⠀You need to specify things: Array<Any> = … explicitly to get the invariant type.)

1 Like

By the way: The reason that Nothing comes up in such cases is not as arbitrary as one might think. The reason behind it is that Nothing is defined to be the subtype of every existing type (just like Any is supertype for everything). Which is a piece of ingenious language design, if you ask me (think about how nicely that plays out for when branches with the Nothing type not changing the whole when expression type, for example). So, because the covariant Any will walk the inheritance structure upwards, it will eventually land at Nothing.

Why it assumes covariance in this case, I don’t know. I’ve always had trouble grasping the generic variance concept. I know it’s very logical, but it just does not want to fit into my head…

1 Like

It seems to infer invariant type in this case.

fun main() {
    val things = arrayOf<Any>(1, 2, 3, "one", "two", "three")
    things[0] = "zero"
    println(things.joinToString())
}
1 Like