Exhaustiveness of When Statements
In Kotlin 1.7, Kotlin will check both when
expressions and when
statements for exhaustiveness in the same way. As a result, we don’t need the no-op exhaustive
extension method we described in Chapter 18 of the
book.
In Kotlin versions up to and including 1.5, The compiler checks when
expressions for exhaustiveness but does not
check when statements. The compiler considers when to be a statement if the value of the entire when expression
is unused.
For example, if using when
to handle elements of the following enum:
enum class Direction {
NORTH, EAST, SOUTH, WEST
}
The compiler will not complain if you miss an element in a statement:
fun runInDirection(direction: Direction) {
when (direction) {
Direction.NORTH -> move(0, -1)
Direction.EAST -> move(1, 0)
Direction.WEST -> move(-1, 0)
// no branch for Direction.SOUTH
}
}
As a result, you can force the compiler to check for exhaustiveness by using the result of the when
, even if your code merely discards it. In the book, we showed how this can be done with a no-op extension method:
val <T> T.exhaustive get() = this
If you call exhaustive
on the result of a when statement, the compiler considers the when to be an expression of type Unit
and checks it for exhaustiveness.
fun walkInDirection(direction: Direction) {
when (direction) {
Direction.NORTH -> move(0, -1)
Direction.EAST -> move(1, 0)
Direction.WEST -> move(-1, 0)
// no branch for Direction.SOUTH
}.exhaustive
}
In Kotlin 1.7 onwards a non-exhaustive when statement will be a compile-time error, and we will not need the exhaustive
extension any more. The “Inline property” refactoring will remove it entirely from the codebase.
Meanwhile, in Kotlin 1.6, non-exhaustive when statements will be reported as compile-time warnings. The example above is reported with the warning:
Non exhaustive 'when' statements on enum will be prohibited in 1.7, add 'SOUTH' branch or 'else' branch instead
To migrate to 1.7, we can configure IntelliJ to report non-exhaustive when statements as errors.
Compiling in progressive mode also reports non-exhaustive when statements as errors.