Dmitry Stakhov
04/02/2024, 7:56 AMsealed class T {
object A: T()
object B: T()
object C: T()
}
fun foo(param: T) {
when (param) {
is A -> { fun1() }
is B, C -> { fun2() }
}
}
fun test() {
foo(mockk<T.C>())
}
the test function throws the kotlin.NoWhenBranchMatchedException
with Kotlin 2.0.0-Beta5
The fix is easy
1. remove mocking -> foo(T.C)
2. add the second is explicitly -> is B, is C -> {}
Is it expected (should we always write is for each branch in the same line) or it should be reported as bug?kirillrakhman
04/02/2024, 8:15 AMC
in a when
branch generates an equality check param == C
whereas is C
generates param is C
.
It looks somewhat expected that param == C
returns false
depending on what mockk<T.C>()
actually returns, e.g. if it generates some synthetic subclass at runtime.Dmitry Stakhov
04/02/2024, 8:46 AMDoes this work in K1?Depends on what we consider as "works" XD The behavior on K1:
fun2
is not called (see the updated sample), but there is no runtime error, the function test
is finished successfully.
I guess this is because the mocked C object doesn't equal C (maybe another object reference) that is not expected by K1 compiler during branches check.
so there is no 'when' expression must be exhaustive, add necessary 'None' branch or 'else' branch instead
error during the compilation
The difference between K1 and K2 is in runtime. K1 ignores the when call, but K2 throws a runtime error.kirillrakhman
04/02/2024, 8:49 AMwhen
expression exhaustive. Exhaustive `when`s get an else branch with the NoWhenBranchMatchedException
.Dmitry Stakhov
04/02/2024, 9:14 AMwhen (param) {
is A -> { fun1() }
is B, C -> { fun2() }
else -> { fun3() }
}
Anyways I am not sure K2 should throw a runtime error or should ignore the else branch if it's not added like K1kirillrakhman
04/02/2024, 9:15 AMdmitriy.novozhilov
04/02/2024, 10:49 AMwhen (param) {
is A -> fun1()
is B, C -> fun2()
}
is equal to
when {
param is A -> fun1()
param is B,
param === C -> fun2()
else -> throw NoWhenBranchMatchedException()
}
I suspect that mockk creates another instance of type C
, which breaks the compiler assumption that there is always only one instance of the object C
, so the param === C
is false and exception raisesDmitry Stakhov
04/02/2024, 10:59 AM