20 July 2018
Kotlin’s when works similarly to Java’s switch. Once upon a time, I heard that when forces you to specify all the branches (when all the branches can be known by the compiler, with enums or sealed-classes), but I didn’t find this to be the case.
IDEs like Android Studio might be able to give you a hint (as it did with switch cases), reminding you to be explicit:

But the documentation for when makes it clearer:
If [
when] is used as an expression, the value of the satisfied branch becomes the value of the overall expression [… and] theelsebranch is mandatory, unless the compiler can prove that all possible cases are covered with branch conditions
So, if we use it as an expression, we get a compiler error!

Sometimes you don’t want to use it as an expression but you still want to explicitly handle all the cases. With switch, we’d often use the default case to express our intent:
void onNext(Result result) {
switch (result.type) {
case COMPLETE:
show(result.data)
break;
case LOADING:
showLoading()
case ERROR:
showError(result.error)
break;
default:
throw new IllegalArgumentException("unknown result type: " + result);
}
}
If we later update the Result.Type enum without updating this logic, we’ll crash. This is preferable to unexpected behaviour.
In Kotlin, we have the else branch instead of a default case, so we could do the same thing with an Exception there.
However, we can make it a compile-time check if we treat the when as an expression with an empty let block:

This doesn’t look great though, and it’s not clear what we’re doing — if I were to read this in the future, I’d probably delete the .let {} thinking it’s doing nothing!
Instead, you can add an extension property with a name that helps explain the purpose:
val <T> T.exhaustive: T
get() = this
This property has a custom getter which returns the object itself, so if we use it on a when block, it’s treated as an expression and the compiler will force us to specify all cases.

I learned this from the Plaid 2.0 project, which is currently under a re-write effort.
Thanks to the team for being patient with my comments and questions!