[FIR] Fix exhaustiveness checking for conditions with equals to object

#KT-37488 Fixed
This commit is contained in:
Dmitriy Novozhilov
2020-03-16 11:04:44 +03:00
parent 3765a1efaf
commit 1b479c49a8
7 changed files with 90 additions and 22 deletions
@@ -149,8 +149,16 @@ class FirWhenExhaustivenessTransformer(private val bodyResolveComponents: BodyRe
override fun visitOperatorCall(operatorCall: FirOperatorCall, data: SealedExhaustivenessData) {
if (operatorCall.operation == FirOperation.EQ) {
val argument = operatorCall.arguments[1]
if (argument is FirConstExpression<*> && argument.value == null) {
data.containsNull = true
when (argument) {
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|)
}
@@ -138,6 +138,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
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")
public void testExtension() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/extension.kt");
@@ -138,6 +138,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
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")
public void testExtension() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/extension.kt");
@@ -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 {
object First: Sealed()
sealed class NonFirst {