Sorry in advance if this is the wrong channel, but...
# compiler
r
Sorry in advance if this is the wrong channel, but I stumbled upon some code that looks like this:
Copy code
import java.util.*

fun main() {
    val x: Any = LinkedList<Int>().apply { add(0) }
    foo(x)
}

fun <T> foo(obj: T) {
    if (obj == arrayListOf(0)) {
        obj.ensureCapacity(100)
    }
}
Surprisingly, this compiles with no warnings, but fails with a
ClassCastException
at runtime. That's because the
obj == arrayListOf(0)
line causes a smart cast of
obj
from
T
to
ArrayList<T>
. But because
List#equals
is defined such that any two lists with the same elements (of any concrete type) are equal, the smart cast here is unsafe. Even more surprisingly to me, this behavior only appears when
obj
has a generic type parameter as its type. The following example fails to compile:
Copy code
import java.util.*

fun main() {
    val x: Any = LinkedList<Int>().apply { add(0) }
    foo(x)
}

fun foo(obj: Any) {
    if (obj == arrayListOf(0)) {
        obj.ensureCapacity(100)
    }
}
I'm curious what's going on here. Why does the compiler accept the first example, though it's unsafe? And given that it accepts the first, why doesn't it accept the second?
d
It's a compiler bug, I've created a KT-85289 for that.
❤️ 1