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:
+10
-2
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
+12
@@ -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
|
||||
}
|
||||
+12
@@ -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 {
|
||||
|
||||
+12
@@ -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 {
|
||||
|
||||
+10
@@ -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");
|
||||
|
||||
+12
@@ -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 {
|
||||
|
||||
+12
@@ -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 {
|
||||
|
||||
+10
@@ -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");
|
||||
|
||||
+12
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user