The problem is that when
have to be exhaustive when you want to use it in return/assign statement.
For example:
// let k be of Any? type:
when (k) {
is Number -> { println("Ok, k is a Number") }
}
This is OK. You don't expect any result. If k
is a number then something will be printed. Otherwise, nothing will happen.
So, the second example:
// k is the same
boolean isNumber = when (k) {
is Number -> true;
}
But, what if boolean is not a number? Code will not compile, because your program would be in indefinite state.
So, what you can do? Your when
have to be exhaustive. So, just add else
. One of the pattern is, for example, to throw IllegalStateException()
if case like your.
fun eval(e: Test): Int = when(e) {
is Test -> 1
else -> throw IllegalArgumentException("This should never happen!")
}
Edit:
Regarding to your comment. e
actually can be something different than Test
. It can be... Nothing.
I am completely aware about possibilities when it can happen and correctness of usage things like this. But, example below is completely OK and compiles without any problem. Maybe with reflection it would have some useful usage.
class Test
fun eval(e: Test): Int =
when(e) {
is Test -> throw IllegalArgumentException()
else -> throw IllegalArgumentException()
}
fun getNothing(): Nothing {
throw IllegalStateException()
}
fun main() {
eval(getNothing())
}