Per default Kotlin only requires when-expressions to be exhaustive if the result is assigned to a variable. However when the result is not assigned to a variable, no exhaustiveness checks are performed.
val foo: Boolean = false
// Error: 'when' expression must be exhaustive, add necessary 'false' branch or 'else' branch instead
val bar = when (foo) {
true -> println("yes")
}
// Compiles without error
val bar = when (foo) {
true -> println("yes")
false -> println("no")
}
// Compiles without error
when (foo) {
true -> println("yes")
}
There is currently an open issue KT-12380 about this and some discussion regarding compiler warnings and exhaustiveness checks.
Additionally there is the cashapp/exhaustive library which adds an @Exhaustive
annotation and contains some discussions how to resolve or mitigate the issue.
If one wants to avoid pulling external dependencies an exhaustiveness check can also easily be added with a tiny utility function.
fun <T> T.exhaustive get() = Unit
val foo: Boolean = false
// Error: 'when' expression must be exhaustive, add necessary 'false' branch or 'else' branch instead
when (foo) {
true -> println("yes")
}.exhaustive
// Compiles without error
when (foo) {
true -> println("yes")
false -> println("no")
}.exhaustive
By defining a dummy extension property (exhaustive
) on all types and accessing it on the return value of the when-expression we effectively get the same behavior as when we assigned the result to a variable and thus force the when-expression to be exhaustive.