Sealed generic exhaustive when

Hello, I’m trying to understand why the following sealing cannot be considered valid by the compiler.
AFAIS every T implementing MyInterface is always either MyClass1 or MyClass2 instance, therefore the compiler should allow for such when.
Thoughts?

sealed interface MyInterface

class MyClass1: MyInterface

class MyClass2: MyInterface

// This sealing doesn't work (when is considered non-exhaustive)
val <T: MyInterface> T.withGenericSealing: Result<T> get() = when(this) {
    is MyClass1 -> Result.success(this)
    is MyClass2 -> Result.success(this)
}

// This works but it's weak
val MyInterface.withInterfaceSealing: Result<MyInterface> get() = when(this){
    is MyClass1 -> Result.success(this)
    is MyClass2 -> Result.success(this)
}

fun usage() {
    val class1 = MyClass1()

    val desiredResult: Result<MyClass1> = class1.withGenericSealing

    val weakResult: Result<MyClass1> = class1.withInterfaceSealing as Result<MyClass1> // Unchecked cast
}

It does not answer your question about when being not exhaustive, but you can do this:

val <T: MyInterface> T.withGenericSealing: Result<T> get() = when(this as MyInterface) {
    is MyClass1 -> Result.success(this)
    is MyClass2 -> Result.success(this)
}

What’s interesting, IDE marks as MyInterface as not needed, so it suggests this may be a bug / missing feature.

1 Like

Please vote for https://youtrack.jetbrains.com/issue/KT-21908

1 Like

Also this one: https://youtrack.jetbrains.com/issue/KT-19645

1 Like