Complete when statement on enumeration

when statement does not check against all possible enumeration values, and the hack

val _ = when(enumValue) { ... }

does not works, do you have any suggestion better than

val dummy = when(enumValue) { ... }

I’m not sure whether it’s any better or not but this hack does work:

enum class Test { One, Two, Three }

operator fun Unit.component1() = Unit

fun main(args: Array<String>) {
    val t = Test.One
    val (_) = when (t) {
        Test.One -> println("1")
        Test.Two -> println("2")
        Test.Three -> println("3")
    }
}

Wow,
two hacks for the same issue!

Maybe some call after the when, like:

when (foo) {
 ...
}.let {  }
1 Like

This blow up if the when never returns:

val (_) = when (foo) {
   EnumFoo.ONE -> TODO()
   EnumFoo.TWO -> TODO()
   EnumFoo.THREE -> TODO()
}

Error:(131, 12) Kotlin: Function ‘component1()’ is ambiguous for this expression:
@InlineOnly public operator inline fun Array<out ???>.component1(): ??? defined in kotlin.collections
@InlineOnly public operator inline fun BooleanArray.component1(): Boolean defined in kotlin.collections
@InlineOnly public operator inline fun ByteArray.component1(): Byte defined in kotlin.collections
@InlineOnly public operator inline fun CharArray.component1(): Char defined in kotlin.collections
@InlineOnly public operator inline fun DoubleArray.component1(): Double defined in kotlin.collections
@InlineOnly public operator inline fun FloatArray.component1(): Float defined in kotlin.collections
@InlineOnly public operator inline fun IntArray.component1(): Int defined in kotlin.collections
@InlineOnly public operator inline fun LongArray.component1(): Long defined in kotlin.collections
@InlineOnly public operator inline fun ShortArray.component1(): Short defined in kotlin.collections
@InlineOnly public operator inline fun List<???>.component1(): ??? defined in kotlin.collections
@InlineOnly public operator inline fun <K, V> Map.Entry<???, ???>.component1(): ??? defined in kotlin.collections

Edit: Never mind, the “operator fun Unit.component1() = Unit” fix it.

I thought at first that the following code, where we enclose the when statement in parentheses, would convert it to an expression:

enum class Test { One, Two, Three }

fun main(args: Array<String>) {
    val t = Test.One
    (when(t) {
        Test.One -> println("1")
        Test.Two -> println("2")
        Test.Three -> println("3")
    })
}

but in fact the compiler just treats it the same and, if branch(es) are commented out, issues a warning (rather than an error) that the when expression should be exhaustive.

I was thinking previously that the compiler permitted a non-exhaustive when statement to simply fall through if none of the branches were applicable but evidently it (or at any rate the current version) does issue a warning. Does anyone know if there’s been a recent change here?

Solution from Plaid works pretty well.
val <T> T.exhaustive: T
get() = this

And then
when (result) {
A → …
B → …
}.exhaustive

will force compiler to handle as an expression

2 Likes