Reified 'as?' produces nullable result
Previously, this was treated as a regular CHECKCAST, causing KT-22410. #Fixed KT-22410 Target versions 1.2.30
This commit is contained in:
@@ -261,7 +261,7 @@ val MethodInsnNode.reificationArgument: ReificationArgument?
|
|||||||
return ReificationArgument(parameterName, nullable, arrayDepth)
|
return ReificationArgument(parameterName, nullable, arrayDepth)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val MethodInsnNode.operationKind: ReifiedTypeInliner.OperationKind? get() =
|
val MethodInsnNode.operationKind: ReifiedTypeInliner.OperationKind? get() =
|
||||||
previous?.previous?.intConstant?.let {
|
previous?.previous?.intConstant?.let {
|
||||||
ReifiedTypeInliner.OperationKind.values().getOrNull(it)
|
ReifiedTypeInliner.OperationKind.values().getOrNull(it)
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-4
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.codegen.optimization.nullCheck
|
package org.jetbrains.kotlin.codegen.optimization.nullCheck
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner
|
||||||
|
import org.jetbrains.kotlin.codegen.inline.operationKind
|
||||||
import org.jetbrains.kotlin.codegen.optimization.boxing.*
|
import org.jetbrains.kotlin.codegen.optimization.boxing.*
|
||||||
import org.jetbrains.kotlin.codegen.optimization.common.OptimizationBasicInterpreter
|
import org.jetbrains.kotlin.codegen.optimization.common.OptimizationBasicInterpreter
|
||||||
import org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue
|
import org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue
|
||||||
@@ -24,6 +26,7 @@ import org.jetbrains.kotlin.codegen.pseudoInsns.isPseudo
|
|||||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
|
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
|
||||||
|
import org.jetbrains.org.objectweb.asm.tree.MethodInsnNode
|
||||||
import org.jetbrains.org.objectweb.asm.tree.TypeInsnNode
|
import org.jetbrains.org.objectweb.asm.tree.TypeInsnNode
|
||||||
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
|
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
|
||||||
|
|
||||||
@@ -53,16 +56,25 @@ class NullabilityInterpreter : OptimizationBasicInterpreter() {
|
|||||||
val defaultResult = super.unaryOperation(insn, value)
|
val defaultResult = super.unaryOperation(insn, value)
|
||||||
val resultType = defaultResult?.type
|
val resultType = defaultResult?.type
|
||||||
|
|
||||||
return when {
|
return when (insn.opcode) {
|
||||||
insn.opcode == Opcodes.CHECKCAST ->
|
Opcodes.CHECKCAST ->
|
||||||
value
|
if (insn.isReifiedSafeAs())
|
||||||
insn.opcode == Opcodes.NEWARRAY || insn.opcode == Opcodes.ANEWARRAY ->
|
StrictBasicValue(resultType)
|
||||||
|
else
|
||||||
|
value
|
||||||
|
Opcodes.NEWARRAY, Opcodes.ANEWARRAY ->
|
||||||
NotNullBasicValue(resultType)
|
NotNullBasicValue(resultType)
|
||||||
else ->
|
else ->
|
||||||
defaultResult
|
defaultResult
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun AbstractInsnNode.isReifiedSafeAs(): Boolean {
|
||||||
|
val marker = previous as? MethodInsnNode ?: return false
|
||||||
|
return ReifiedTypeInliner.isOperationReifiedMarker(marker)
|
||||||
|
&& marker.operationKind == ReifiedTypeInliner.OperationKind.SAFE_AS
|
||||||
|
}
|
||||||
|
|
||||||
override fun naryOperation(insn: AbstractInsnNode, values: List<BasicValue>): BasicValue? {
|
override fun naryOperation(insn: AbstractInsnNode, values: List<BasicValue>): BasicValue? {
|
||||||
val defaultResult = super.naryOperation(insn, values)
|
val defaultResult = super.naryOperation(insn, values)
|
||||||
val resultType = defaultResult?.type
|
val resultType = defaultResult?.type
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
fun box(): String {
|
||||||
|
defineFunc<String>()
|
||||||
|
|
||||||
|
func(1)
|
||||||
|
|
||||||
|
return if (testedEquals) "OK" else "Fail"
|
||||||
|
}
|
||||||
|
|
||||||
|
var func: (Any) -> Unit = {}
|
||||||
|
|
||||||
|
var testedEquals = false
|
||||||
|
|
||||||
|
inline fun <reified T> defineFunc() {
|
||||||
|
func = {
|
||||||
|
val nullable = it as? T
|
||||||
|
|
||||||
|
if (nullable == null)
|
||||||
|
testedEquals = true
|
||||||
|
}
|
||||||
|
}
|
||||||
Generated
+6
@@ -12672,6 +12672,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt22410.kt")
|
||||||
|
public void testKt22410() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/nullCheckOptimization/kt22410.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kt7774.kt")
|
@TestMetadata("kt7774.kt")
|
||||||
public void testKt7774() throws Exception {
|
public void testKt7774() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/nullCheckOptimization/kt7774.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/nullCheckOptimization/kt7774.kt");
|
||||||
|
|||||||
+6
@@ -12672,6 +12672,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt22410.kt")
|
||||||
|
public void testKt22410() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/nullCheckOptimization/kt22410.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kt7774.kt")
|
@TestMetadata("kt7774.kt")
|
||||||
public void testKt7774() throws Exception {
|
public void testKt7774() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/nullCheckOptimization/kt7774.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/nullCheckOptimization/kt7774.kt");
|
||||||
|
|||||||
+6
@@ -12672,6 +12672,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt22410.kt")
|
||||||
|
public void testKt22410() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/nullCheckOptimization/kt22410.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kt7774.kt")
|
@TestMetadata("kt7774.kt")
|
||||||
public void testKt7774() throws Exception {
|
public void testKt7774() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/nullCheckOptimization/kt7774.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/nullCheckOptimization/kt7774.kt");
|
||||||
|
|||||||
+6
@@ -13776,6 +13776,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt22410.kt")
|
||||||
|
public void testKt22410() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/nullCheckOptimization/kt22410.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kt7774.kt")
|
@TestMetadata("kt7774.kt")
|
||||||
public void testKt7774() throws Exception {
|
public void testKt7774() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/nullCheckOptimization/kt7774.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/nullCheckOptimization/kt7774.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user