Kotlin's smart cast fails simple non-nullability deduction

188 Views Asked by At

Trying to understand why Kotlin's smart cast doesn't trigger for a fairly simple use case:

val x: Int? = 1

val notNull: Boolean = x != null

if (notNull) {
    val y: Int = x // fails to smart cast
}

However it works if we remove the intermediate val:

val x: Int? = 1

if (x != null) {
    val y: Int = x // smart cast works
}

val essentially defines a final value, so I don't see the reason why the first version wouldn't work.

For the record Java's analog to this (https://github.com/uber/NullAway) also fails for such use cases so there might be some underlying complication that makes such deductions impossible?

1

There are 1 best solutions below

2
Willi Mentzel On

You have to see it like that. notNull is assigned with true (the result of x != null). After this line there is no information available for the compiler to make the connection between that value and the nullability of x.

It's basically the same as writing it like this right away:

val notNull = true // this is all the compiler knows the time it evaluates the if expression.

if (notNull) {
    val y: Int = x // fails to smart cast
}

You could argue the same for

if (x != null) {
    val y: Int = x // smart cast works
}

you will say. True, but in this case the compiler offers x in the if block right away as non-null. That's where it draws the line. If you don't stop somewhere you will end up with a lot of inference making the process of compilation less efficient.