[FIR] Fix exhaustiveness check when subject has flexible type
This commit is contained in:
+4
-1
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeLookupTagBasedType
|
||||
import org.jetbrains.kotlin.fir.types.ConeNullability
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.lowerBoundIfFlexible
|
||||
import org.jetbrains.kotlin.fir.visitors.*
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
|
||||
@@ -46,7 +47,9 @@ class FirWhenExhaustivenessTransformer(private val bodyResolveComponents: BodyRe
|
||||
?: (whenExpression.subject as? FirQualifiedAccessExpression)?.typeRef) as? FirResolvedTypeRef
|
||||
?: return null
|
||||
|
||||
val lookupTag = (typeRef.type as? ConeLookupTagBasedType)?.lookupTag ?: return null
|
||||
// TODO: add some report logic about flexible type (see WHEN_ENUM_CAN_BE_NULL_IN_JAVA diagnostic in old frontend)
|
||||
val type = typeRef.type.lowerBoundIfFlexible()
|
||||
val lookupTag = (type as? ConeLookupTagBasedType)?.lookupTag ?: return null
|
||||
val nullable = typeRef.type.nullability == ConeNullability.NULLABLE
|
||||
val isExhaustive = when {
|
||||
((lookupTag as? ConeClassLikeLookupTag)?.classId == bodyResolveComponents.session.builtinTypes.booleanType.id) -> {
|
||||
|
||||
+16
-3
@@ -1,3 +1,5 @@
|
||||
// IGNORE_LIGHT_TREE
|
||||
|
||||
// FILE: Utils.java
|
||||
|
||||
public class Utils {
|
||||
@@ -12,12 +14,23 @@ enum class E {
|
||||
A, B, C
|
||||
}
|
||||
|
||||
fun test() {
|
||||
fun test_1() {
|
||||
val e = Utils.getEnum()
|
||||
val s = when (e) {
|
||||
E.A, null -> return
|
||||
null -> return
|
||||
E.A -> ""
|
||||
E.B -> ""
|
||||
E.C -> ""
|
||||
}
|
||||
s.<!UNRESOLVED_REFERENCE!>length<!>
|
||||
s.length
|
||||
}
|
||||
|
||||
fun test_2() {
|
||||
val e = Utils.getEnum()
|
||||
val s = when (e) {
|
||||
E.A -> ""
|
||||
E.B -> ""
|
||||
E.C -> ""
|
||||
}
|
||||
s.length
|
||||
}
|
||||
+24
-5
@@ -32,11 +32,14 @@ FILE: main.kt
|
||||
}
|
||||
|
||||
}
|
||||
public final fun test(): R|kotlin/Unit| {
|
||||
public final fun test_1(): R|kotlin/Unit| {
|
||||
lval e: R|ft<E, E?>!| = Q|Utils|.R|/Utils.getEnum|()
|
||||
lval s: R|kotlin/Unit| = when (R|<local>/e|) {
|
||||
==($subj$, Q|E|.R|/E.A|) || ==($subj$, Null(null)) -> {
|
||||
^test Unit
|
||||
lval s: R|kotlin/String| = when (R|<local>/e|) {
|
||||
==($subj$, Null(null)) -> {
|
||||
^test_1 Unit
|
||||
}
|
||||
==($subj$, Q|E|.R|/E.A|) -> {
|
||||
String()
|
||||
}
|
||||
==($subj$, Q|E|.R|/E.B|) -> {
|
||||
String()
|
||||
@@ -46,5 +49,21 @@ FILE: main.kt
|
||||
}
|
||||
}
|
||||
|
||||
R|<local>/s|.<Unresolved name: length>#
|
||||
R|<local>/s|.R|kotlin/String.length|
|
||||
}
|
||||
public final fun test_2(): R|kotlin/Unit| {
|
||||
lval e: R|ft<E, E?>!| = Q|Utils|.R|/Utils.getEnum|()
|
||||
lval s: R|kotlin/String| = when (R|<local>/e|) {
|
||||
==($subj$, Q|E|.R|/E.A|) -> {
|
||||
String()
|
||||
}
|
||||
==($subj$, Q|E|.R|/E.B|) -> {
|
||||
String()
|
||||
}
|
||||
==($subj$, Q|E|.R|/E.C|) -> {
|
||||
String()
|
||||
}
|
||||
}
|
||||
|
||||
R|<local>/s|.R|kotlin/String.length|
|
||||
}
|
||||
+5
-5
@@ -78,6 +78,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
|
||||
runTest("compiler/fir/resolve/testData/resolve/enumWithCompanion.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("exhaustiveWhenAndFlexibleType.kt")
|
||||
public void testExhaustiveWhenAndFlexibleType() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/exhaustiveWhenAndFlexibleType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("exhaustiveness_boolean.kt")
|
||||
public void testExhaustiveness_boolean() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/exhaustiveness_boolean.kt");
|
||||
@@ -1036,11 +1041,6 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
|
||||
runTest("compiler/fir/resolve/testData/resolve/problems/definitelyNotNullAmbiguity.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("exhaustiveWhenAndFlexibleType.kt")
|
||||
public void testExhaustiveWhenAndFlexibleType() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/problems/exhaustiveWhenAndFlexibleType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("incorrectSuperCall.kt")
|
||||
public void testIncorrectSuperCall() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/problems/incorrectSuperCall.kt");
|
||||
|
||||
Generated
+5
-5
@@ -78,6 +78,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
||||
runTest("compiler/fir/resolve/testData/resolve/enumWithCompanion.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("exhaustiveWhenAndFlexibleType.kt")
|
||||
public void testExhaustiveWhenAndFlexibleType() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/exhaustiveWhenAndFlexibleType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("exhaustiveness_boolean.kt")
|
||||
public void testExhaustiveness_boolean() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/exhaustiveness_boolean.kt");
|
||||
@@ -1036,11 +1041,6 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
||||
runTest("compiler/fir/resolve/testData/resolve/problems/definitelyNotNullAmbiguity.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("exhaustiveWhenAndFlexibleType.kt")
|
||||
public void testExhaustiveWhenAndFlexibleType() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/problems/exhaustiveWhenAndFlexibleType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("incorrectSuperCall.kt")
|
||||
public void testIncorrectSuperCall() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/problems/incorrectSuperCall.kt");
|
||||
|
||||
Reference in New Issue
Block a user