[FIR] Properly process `!is` branches in exhaustiveness checker In the scope of KT-80461 the new simplified mechanism for checking exhaustiveness with sealed subject was introduced. For `!is Type` it considered all the sealed subclasses which are not subtype of `Type` to be checked. But it's actually incorrect in case if the `Type` is an inheritor of the sealed subclass itself, which caused false-negative `NO_ELSE_IN_WHEN` happen. ^KT-82841 Fixed
diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirWhenExhaustivenessComputer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirWhenExhaustivenessComputer.kt index a249c22..00288df 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirWhenExhaustivenessComputer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirWhenExhaustivenessComputer.kt
@@ -511,9 +511,9 @@ } private fun processBranchUsingSubtyping(symbolToCheck: FirClassSymbol<*>, isNegated: Boolean, data: Info) { - val predicate: (FirClassSymbol<*>) -> Boolean = { - it.isSubclassOf( - symbolToCheck.toLookupTag(), + fun FirClassSymbol<*>.isSubclassOf(other: FirClassSymbol<*>): Boolean { + return this.isSubclassOf( + other.toLookupTag(), data.session, isStrict = false, lookupInterfaces = true @@ -522,10 +522,14 @@ val subclassesCheckedByTheBranch = when (isNegated) { // `<subj> is Type`, `<subj> == Type` branches - false -> data.allSubclasses.filter(predicate) + false -> data.allSubclasses.filter { subclass -> + subclass.isSubclassOf(symbolToCheck) + } // `<subj> !is Type`, `<subj> != Type` branches - true -> data.allSubclasses.filterNot(predicate) + true -> data.allSubclasses.filter { subclass -> + !subclass.isSubclassOf(symbolToCheck) && !symbolToCheck.isSubclassOf(subclass) + } } // subclassesCheckedByTheBranch
diff --git a/compiler/testData/diagnostics/tests/sealed/nonExhaustiveByNegation.fir.kt b/compiler/testData/diagnostics/tests/sealed/nonExhaustiveByNegation.fir.kt deleted file mode 100644 index 279badd..0000000 --- a/compiler/testData/diagnostics/tests/sealed/nonExhaustiveByNegation.fir.kt +++ /dev/null
@@ -1,17 +0,0 @@ -// RUN_PIPELINE_TILL: BACKEND -// ISSUE: KT-82841 - -sealed class Base - -abstract class Derived : Base() - -class Implementation : Derived() - -fun test_1(x: Base) { - val value = when (x) { - !is Implementation -> 1 - } -} - -/* GENERATED_FIR_TAGS: classDeclaration, functionDeclaration, integerLiteral, isExpression, localProperty, -propertyDeclaration, sealed, whenExpression, whenWithSubject */
diff --git a/compiler/testData/diagnostics/tests/sealed/nonExhaustiveByNegation.kt b/compiler/testData/diagnostics/tests/sealed/nonExhaustiveByNegation.kt index 4bf1d32..2fe9b60 100644 --- a/compiler/testData/diagnostics/tests/sealed/nonExhaustiveByNegation.kt +++ b/compiler/testData/diagnostics/tests/sealed/nonExhaustiveByNegation.kt
@@ -1,4 +1,5 @@ -// RUN_PIPELINE_TILL: BACKEND +// RUN_PIPELINE_TILL: FRONTEND +// FIR_IDENTICAL // ISSUE: KT-82841 sealed class Base