‘when’ expression requires to be exhaustive, even be 'else' branch is empty

I have an enum with 7 states, also I have several ‘when’ statements:

when(state) {
States.state1 → doForState1
States.state2, Stetes.state3 → doForState2and3
} // generate error that I need add States 4,5,6,7 or else branch

As result, I added the else branch:

when(state) {
States.state1 → doForState1
States.state2, Stetes.state3 → doForState2and3
else → {} // do nothing
}
Early I had warnings only, but. Why I got the error after updating the version of Kotlin? Why compilator require an empty ‘else’ branch?

The compiler requires the when to be exhaustive.

As “why”, well the language designers following feedback decided that it was better

1 Like

Initially, when could be exhaustive or non-exhaustive depending on whether it was used as an expression. That created code ambiguity as exactly the same code could be treated differently by the compiler, which might confuse the developer and cause bugs. As exhaustive whens are generally considered to be better for the code quality, all whens were made exhaustive by default. In 1.6 compiler started to generate warnings if they are not exhaustive and in 1.7 the warning was turned into an error.

BTW, don’t ignore warnings! They are generated for a reason.

See: https://youtrack.jetbrains.com/issue/KT-47709

1 Like

I think a warning should be generated to help the developer see a potential bug, evaluate it, fix it if necessary, or ignore the warning.
Thus, I think an error should be replaced by a warning. Because else → {} provides no additional information and can confuse the programmer, giving the impression that he wanted, but forgot to write code, although by design nothing should happen otherwise. Maybe should add a special operator ‘elseDoNothing’? Example:
when (newState) {
States.state1 → …
States.stete5 → …
elseDoNothing (or else do nothing)
}

I personally don’t think the language needs to be expanded for this.

I use else -> Unit more.
But you could also:

  • create empty function fun ignoreOtherBranches() = Unit
  • create 'typealias Unit = IgnoreOtherBranches`

Which would lead to:

when(newState) {
     States.state1 -> ignoreOtherBranches()
     else -> IgnoreOtherBranches
}

So, no need for another language addition to make it more understandable.

4 Likes

Thanks, great idea.