Smart cast issue: if-else and when


#1

I found some issues with smart cast, here two examples:

fun exampleElse(vararg args: String) {
    val something: Any = TODO()
    if (something is String) throw Exception()
    else // <---
        if (something !is Long) throw Exception()
    something.dec()
}

fun exampleWhen(vararg args: String) {
    val something: Any = TODO()
    when (something) {
        !is Long -> throw Exception()
    }
    something.dec()
}

In the first example it is possible to invoke dec() but, when else is not commented, the IntelliJ’s auto completition fails.

In the second case smart cast fails indifferently.

Edit: Kotlin version 1.2


#2

The comment probably changes whether the if is independent or not. Without the comment it will be part, and analysis of multiple if statements may be incomplete (in actuality the analysis is quite tricky.

For the second one, it is clear that this is also not analysed completely.


#3

The first example compiles always, but autocomplete works sometimes.


#4

I have noticed that when doesn’t seem to lend itself to (admittedly, complex) smart casts. For example, this doesn’t work:

val args = arrayOf(Any)
when {
   args.isEmpty() -> throw IllegalArgumentException("Empty args")
   args[0] !is Foo -> throw IllegalArgumentException("Invalid arg type")
   else -> args[0].doFooThing()
}

#5

May that be an issue of it being an array rather than an issue of when?


#6

Could be.


#7

Arrays are mutable. There is no guarantee that multiple accesses of args[0] will return the same value.


#8

Missing autocomplete for example ‘exampleElse’ using Kotlin 1.2.10, too.