[FIR] Fix exhaustiveness checking for conditions with equals to object
#KT-37488 Fixed
This commit is contained in:
+10
-2
@@ -149,8 +149,16 @@ class FirWhenExhaustivenessTransformer(private val bodyResolveComponents: BodyRe
|
|||||||
override fun visitOperatorCall(operatorCall: FirOperatorCall, data: SealedExhaustivenessData) {
|
override fun visitOperatorCall(operatorCall: FirOperatorCall, data: SealedExhaustivenessData) {
|
||||||
if (operatorCall.operation == FirOperation.EQ) {
|
if (operatorCall.operation == FirOperation.EQ) {
|
||||||
val argument = operatorCall.arguments[1]
|
val argument = operatorCall.arguments[1]
|
||||||
if (argument is FirConstExpression<*> && argument.value == null) {
|
when (argument) {
|
||||||
data.containsNull = true
|
is FirConstExpression<*> -> {
|
||||||
|
if (argument.value == null) {
|
||||||
|
data.containsNull = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
is FirResolvedQualifier -> {
|
||||||
|
argument.typeRef.accept(this, data)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
// ISSUE: KT-37488
|
||||||
|
|
||||||
|
sealed class A
|
||||||
|
|
||||||
|
class B : A()
|
||||||
|
object C : A()
|
||||||
|
|
||||||
|
fun takeString(s: String) {}
|
||||||
|
|
||||||
|
fun test_1(a: A) {
|
||||||
|
val s = when(a) {
|
||||||
|
is B -> ""
|
||||||
|
is C -> ""
|
||||||
|
}
|
||||||
|
takeString(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test_2(a: A) {
|
||||||
|
val s = when(a) {
|
||||||
|
is B -> ""
|
||||||
|
C -> ""
|
||||||
|
}
|
||||||
|
takeString(s)
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
FILE: exhaustiveness_sealedObject.kt
|
||||||
|
public sealed class A : R|kotlin/Any| {
|
||||||
|
private constructor(): R|A| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final class B : R|A| {
|
||||||
|
public constructor(): R|B| {
|
||||||
|
super<R|A|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final object C : R|A| {
|
||||||
|
private constructor(): R|C| {
|
||||||
|
super<R|A|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final fun takeString(s: R|kotlin/String|): R|kotlin/Unit| {
|
||||||
|
}
|
||||||
|
public final fun test_1(a: R|A|): R|kotlin/Unit| {
|
||||||
|
lval s: R|kotlin/String| = when (R|<local>/a|) {
|
||||||
|
($subj$ is R|B|) -> {
|
||||||
|
String()
|
||||||
|
}
|
||||||
|
($subj$ is R|C|) -> {
|
||||||
|
String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
R|/takeString|(R|<local>/s|)
|
||||||
|
}
|
||||||
|
public final fun test_2(a: R|A|): R|kotlin/Unit| {
|
||||||
|
lval s: R|kotlin/String| = when (R|<local>/a|) {
|
||||||
|
($subj$ is R|B|) -> {
|
||||||
|
String()
|
||||||
|
}
|
||||||
|
==($subj$, Q|C|) -> {
|
||||||
|
String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
R|/takeString|(R|<local>/s|)
|
||||||
|
}
|
||||||
+5
@@ -138,6 +138,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
|
|||||||
runTest("compiler/fir/resolve/testData/resolve/exhaustiveness_sealedClass.kt");
|
runTest("compiler/fir/resolve/testData/resolve/exhaustiveness_sealedClass.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("exhaustiveness_sealedObject.kt")
|
||||||
|
public void testExhaustiveness_sealedObject() throws Exception {
|
||||||
|
runTest("compiler/fir/resolve/testData/resolve/exhaustiveness_sealedObject.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("extension.kt")
|
@TestMetadata("extension.kt")
|
||||||
public void testExtension() throws Exception {
|
public void testExtension() throws Exception {
|
||||||
runTest("compiler/fir/resolve/testData/resolve/extension.kt");
|
runTest("compiler/fir/resolve/testData/resolve/extension.kt");
|
||||||
|
|||||||
Generated
+5
@@ -138,6 +138,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
|||||||
runTest("compiler/fir/resolve/testData/resolve/exhaustiveness_sealedClass.kt");
|
runTest("compiler/fir/resolve/testData/resolve/exhaustiveness_sealedClass.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("exhaustiveness_sealedObject.kt")
|
||||||
|
public void testExhaustiveness_sealedObject() throws Exception {
|
||||||
|
runTest("compiler/fir/resolve/testData/resolve/exhaustiveness_sealedObject.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("extension.kt")
|
@TestMetadata("extension.kt")
|
||||||
public void testExtension() throws Exception {
|
public void testExtension() throws Exception {
|
||||||
runTest("compiler/fir/resolve/testData/resolve/extension.kt");
|
runTest("compiler/fir/resolve/testData/resolve/extension.kt");
|
||||||
|
|||||||
-20
@@ -1,20 +0,0 @@
|
|||||||
sealed class Sealed {
|
|
||||||
object First: Sealed()
|
|
||||||
sealed class NonFirst {
|
|
||||||
object Second: NonFirst()
|
|
||||||
object Third: NonFirst()
|
|
||||||
object Fourth: Sealed()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun foo(s: Sealed, nf: Sealed.NonFirst): Int {
|
|
||||||
val si = when(s) {
|
|
||||||
Sealed.First -> 1
|
|
||||||
Sealed.NonFirst.Fourth -> 4
|
|
||||||
}
|
|
||||||
val nfi = when(nf) {
|
|
||||||
Sealed.NonFirst.Second -> 2
|
|
||||||
Sealed.NonFirst.Third -> 3
|
|
||||||
}
|
|
||||||
return si <!UNRESOLVED_REFERENCE!>+<!> nfi
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
sealed class Sealed {
|
sealed class Sealed {
|
||||||
object First: Sealed()
|
object First: Sealed()
|
||||||
sealed class NonFirst {
|
sealed class NonFirst {
|
||||||
|
|||||||
Reference in New Issue
Block a user