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:
Dmitry Petrov
2018-01-24 14:24:56 +03:00
parent bd25bf14df
commit 5e34f290ce
7 changed files with 61 additions and 5 deletions
@@ -261,7 +261,7 @@ val MethodInsnNode.reificationArgument: ReificationArgument?
return ReificationArgument(parameterName, nullable, arrayDepth)
}
private val MethodInsnNode.operationKind: ReifiedTypeInliner.OperationKind? get() =
val MethodInsnNode.operationKind: ReifiedTypeInliner.OperationKind? get() =
previous?.previous?.intConstant?.let {
ReifiedTypeInliner.OperationKind.values().getOrNull(it)
}
@@ -16,6 +16,8 @@
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.common.OptimizationBasicInterpreter
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.Type
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.analysis.BasicValue
@@ -53,16 +56,25 @@ class NullabilityInterpreter : OptimizationBasicInterpreter() {
val defaultResult = super.unaryOperation(insn, value)
val resultType = defaultResult?.type
return when {
insn.opcode == Opcodes.CHECKCAST ->
value
insn.opcode == Opcodes.NEWARRAY || insn.opcode == Opcodes.ANEWARRAY ->
return when (insn.opcode) {
Opcodes.CHECKCAST ->
if (insn.isReifiedSafeAs())
StrictBasicValue(resultType)
else
value
Opcodes.NEWARRAY, Opcodes.ANEWARRAY ->
NotNullBasicValue(resultType)
else ->
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? {
val defaultResult = super.naryOperation(insn, values)
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
}
}
@@ -12672,6 +12672,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
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")
public void testKt7774() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/nullCheckOptimization/kt7774.kt");
@@ -12672,6 +12672,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
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")
public void testKt7774() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/nullCheckOptimization/kt7774.kt");
@@ -12672,6 +12672,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
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")
public void testKt7774() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/nullCheckOptimization/kt7774.kt");
@@ -13776,6 +13776,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
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")
public void testKt7774() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/nullCheckOptimization/kt7774.kt");