An is branch in when (if and when) smart-casts the subject (Smart Casts), and because the compiler knows every subtype of a sealed type, it checks that the branches cover them all, with no else. Compile this function together with Sealed.kt from Sealed Interfaces, forget two cases, and the build stops.
fun describe(action: CartAction): String = when (action) {
is Add if action.quantity > 5 -> "rejected: at most 5 copies"
is Add -> "add ${action.quantity} x book ${action.bookId}"
is Remove -> "remove book ${action.bookId}"
}Output
$ kotlinc Sealed.kt Missing.kt -include-runtime -d Missing.jar
Missing.kt:1:44: error: 'when' expression must be exhaustive. Add the 'Checkout', 'Clear'
branches or an 'else' branch.
fun describe(action: CartAction): String = when (action) {
^^^^is Add if ... is a guard condition (stable since Kotlin 2.2.0): it matches only when the type test and the condition both hold, and it never counts toward exhaustiveness, so the plain is Add must follow. Since Kotlin 1.7.0 a when statement over a sealed, enum or Boolean subject must be exhaustive too. Don't silence the error with else ->: it would swallow every subtype added later, hiding the code a new case breaks.