In a `when` expression over the value of some type...
# getting-started
y
In a
when
expression over the value of some type
T?
, it is not enough to have the cases
is T
and
null
(or
is T
and
!is T
). you still need an
else
case to be exhaustive. is this a known bug, or is there a reason for this?
a
are you in an
inline reified
method?
y
I don't think so? it's an
override fun
of an
interface
, the implementor is an
object
a
kotlin, along with java, uses type erasure of generics at runtime, so you don't actually know what type
T
is at runtime, unless you are using an inline reified function
y
so
T
unifies with
T?
at runtime?
a
is T
doesn't really do what you think it does at runtime
I'd recommend googling things like "kotlin type erasure generics inline reified" etc.
can probably explain it better than I can
y
thank you, I'll re-read about
reified
. anyway, the compiler seems to reject this even here
Copy code
inline fun <reified T> theValueOf(k: T?): Int =
    when (k) {
        is T -> 1
        null -> 0
    }
and here
Copy code
inline fun theValueOf(k: Int?): Int =
    when (k) {
        is Int -> 1
        null -> 0
    }
e
in this case, it's because the compiler only tries keeping track of exhaustive for enums and sealed classes
👍 1
Copy code
sealed interface X
class Y : X
class Z : X

fun f(x: X?) = when (x) {
    is Y -> 1
    is Z -> 2
    null -> 0
}
this works, for example
y
indeed, which is where my surprise came from. my (very naive) expectation would be that
T?
would be treated as sealed class (of
T
and
null
)
e
I think a more reasonable expectation is that the
when
cases cover the types
T
and
Nothing?
, whose union is
T?
, but the compiler isn't currently about to use that
y
it's also surprising (to me) that
is T
and
!is T
is not enough to be exhaustive.
e
https://youtrack.jetbrains.com/issue/KT-47709 under current language design, only enums, sealed, Boolean (which is basically like a small enum), and nullable versions of them are handled for when exhaustiveness
❤️ 1
checking
is T
doesn't do what you want unless `<reified T : Any>`; also if your
null
check is first, then the subject will be smart-cast to a
T & Any
in following branches (such as
else
)