JVM: correctly merge typed null values

1. merge(null of type A, null of type B) = null of unknown type;
2. merge(null of type A, something of type B) = merge(unknown null, B).

^KT-52311 Fixed
This commit is contained in:
pyos
2022-05-10 15:29:51 +02:00
committed by teamcity
parent dcdd1cd14e
commit 513ef575ce
11 changed files with 160 additions and 2 deletions
@@ -161,7 +161,7 @@ private fun Type.isIntLike(): Boolean = when (sort) {
}
// Represents [ACONST_NULL, CHECKCAST Type] sequence result.
internal class TypedNullValue(type: Type) : BasicValue(type)
internal class TypedNullValue(type: Type) : StrictBasicValue(type)
// Preserves nulls through CHECKCASTS.
private class NullCheckcastAwareOptimizationBasicInterpreter : OptimizationBasicInterpreter() {
@@ -171,4 +171,12 @@ private class NullCheckcastAwareOptimizationBasicInterpreter : OptimizationBasic
}
return super.unaryOperation(insn, value)
}
}
override fun merge(v: BasicValue, w: BasicValue): BasicValue =
when {
v is TypedNullValue && w is TypedNullValue -> if (v.type == w.type) v else StrictBasicValue.NULL_VALUE
v is TypedNullValue -> super.merge(StrictBasicValue.NULL_VALUE, w)
w is TypedNullValue -> super.merge(v, StrictBasicValue.NULL_VALUE)
else -> super.merge(v, w)
}
}
@@ -10209,6 +10209,18 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/coroutines/kt51718.kt");
}
@Test
@TestMetadata("kt52311_nullOnLeft.kt")
public void testKt52311_nullOnLeft() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/kt52311_nullOnLeft.kt");
}
@Test
@TestMetadata("kt52311_nullOnRight.kt")
public void testKt52311_nullOnRight() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/kt52311_nullOnRight.kt");
}
@Test
@TestMetadata("lastExpressionIsLoop.kt")
public void testLastExpressionIsLoop() throws Exception {
@@ -0,0 +1,29 @@
// WITH_STDLIB
// WITH_COROUTINES
import helpers.*
import kotlin.coroutines.*
import kotlin.coroutines.intrinsics.*
fun someCondition() = true
suspend fun suspendHere() = suspendCoroutineUninterceptedOrReturn {
it.resume(Unit)
COROUTINE_SUSPENDED
}
fun expectString(x: String?) = x!!
suspend fun foo(): String {
var x: String? = null
if (someCondition()) {
x = "OK"
}
suspendHere()
return expectString(x)
}
fun box(): String {
var result = "fail"
suspend { result = foo() }.startCoroutine(EmptyContinuation)
return result
}
@@ -0,0 +1,29 @@
// WITH_STDLIB
// WITH_COROUTINES
import helpers.*
import kotlin.coroutines.*
import kotlin.coroutines.intrinsics.*
fun someCondition() = false
suspend fun suspendHere() = suspendCoroutineUninterceptedOrReturn {
it.resume(Unit)
COROUTINE_SUSPENDED
}
fun expectString(x: String?) = x!!
suspend fun foo(): String {
var x: String? = "OK"
if (someCondition()) {
x = null as String?
}
suspendHere()
return expectString(x)
}
fun box(): String {
var result = "fail"
suspend { result = foo() }.startCoroutine(EmptyContinuation)
return result
}
@@ -10089,6 +10089,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/coroutines/kt51718.kt");
}
@Test
@TestMetadata("kt52311_nullOnLeft.kt")
public void testKt52311_nullOnLeft() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/kt52311_nullOnLeft.kt");
}
@Test
@TestMetadata("kt52311_nullOnRight.kt")
public void testKt52311_nullOnRight() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/kt52311_nullOnRight.kt");
}
@Test
@TestMetadata("lastExpressionIsLoop.kt")
public void testLastExpressionIsLoop() throws Exception {
@@ -10209,6 +10209,18 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/coroutines/kt51718.kt");
}
@Test
@TestMetadata("kt52311_nullOnLeft.kt")
public void testKt52311_nullOnLeft() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/kt52311_nullOnLeft.kt");
}
@Test
@TestMetadata("kt52311_nullOnRight.kt")
public void testKt52311_nullOnRight() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/kt52311_nullOnRight.kt");
}
@Test
@TestMetadata("lastExpressionIsLoop.kt")
public void testLastExpressionIsLoop() throws Exception {
@@ -7944,6 +7944,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/coroutines/kt51718.kt");
}
@TestMetadata("kt52311_nullOnLeft.kt")
public void testKt52311_nullOnLeft() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/kt52311_nullOnLeft.kt");
}
@TestMetadata("kt52311_nullOnRight.kt")
public void testKt52311_nullOnRight() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/kt52311_nullOnRight.kt");
}
@TestMetadata("lastExpressionIsLoop.kt")
public void testLastExpressionIsLoop() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/lastExpressionIsLoop.kt");
@@ -7181,6 +7181,18 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/coroutines/kt51718.kt");
}
@Test
@TestMetadata("kt52311_nullOnLeft.kt")
public void testKt52311_nullOnLeft() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/kt52311_nullOnLeft.kt");
}
@Test
@TestMetadata("kt52311_nullOnRight.kt")
public void testKt52311_nullOnRight() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/kt52311_nullOnRight.kt");
}
@Test
@TestMetadata("lastExpressionIsLoop.kt")
public void testLastExpressionIsLoop() throws Exception {
@@ -7223,6 +7223,18 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/coroutines/kt51718.kt");
}
@Test
@TestMetadata("kt52311_nullOnLeft.kt")
public void testKt52311_nullOnLeft() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/kt52311_nullOnLeft.kt");
}
@Test
@TestMetadata("kt52311_nullOnRight.kt")
public void testKt52311_nullOnRight() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/kt52311_nullOnRight.kt");
}
@Test
@TestMetadata("lastExpressionIsLoop.kt")
public void testLastExpressionIsLoop() throws Exception {
@@ -6354,6 +6354,16 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
runTest("compiler/testData/codegen/box/coroutines/kt51718.kt");
}
@TestMetadata("kt52311_nullOnLeft.kt")
public void testKt52311_nullOnLeft() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/kt52311_nullOnLeft.kt");
}
@TestMetadata("kt52311_nullOnRight.kt")
public void testKt52311_nullOnRight() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/kt52311_nullOnRight.kt");
}
@TestMetadata("lastExpressionIsLoop.kt")
public void testLastExpressionIsLoop() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/lastExpressionIsLoop.kt");
@@ -8065,6 +8065,18 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest
runTest("compiler/testData/codegen/box/coroutines/kt51718.kt");
}
@Test
@TestMetadata("kt52311_nullOnLeft.kt")
public void testKt52311_nullOnLeft() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/kt52311_nullOnLeft.kt");
}
@Test
@TestMetadata("kt52311_nullOnRight.kt")
public void testKt52311_nullOnRight() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/kt52311_nullOnRight.kt");
}
@Test
@TestMetadata("lastExpressionIsLoop.kt")
public void testLastExpressionIsLoop() throws Exception {