JVM_IR KT-47398 handle @EnhancedNullability String subject as in 1.0
This commit is contained in:
committed by
teamcityserver
parent
c26d71c4ef
commit
0104b1275f
+12
@@ -42767,12 +42767,24 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/when/stringOptimization/duplicatingItemsSameHashCode3.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("enhancedNullability.kt")
|
||||
public void testEnhancedNullability() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/when/stringOptimization/enhancedNullability.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("expression.kt")
|
||||
public void testExpression() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/when/stringOptimization/expression.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("flexibleNullability.kt")
|
||||
public void testFlexibleNullability() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/when/stringOptimization/flexibleNullability.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nullability.kt")
|
||||
public void testNullability() throws Exception {
|
||||
|
||||
+15
-4
@@ -9,10 +9,11 @@ import org.jetbrains.kotlin.codegen.`when`.SwitchCodegen.Companion.preferLookupO
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.dump
|
||||
import org.jetbrains.kotlin.ir.util.hasAnnotation
|
||||
import org.jetbrains.kotlin.ir.util.isTrueConst
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import java.util.*
|
||||
|
||||
// TODO: eliminate the temporary variable
|
||||
class SwitchGenerator(private val expression: IrWhen, private val data: BlockInfo, private val codegen: ExpressionCodegen) {
|
||||
@@ -446,9 +447,19 @@ class SwitchGenerator(private val expression: IrWhen, private val data: BlockInf
|
||||
hashAndSwitchLabels.add(ValueToLabel(key, Label()))
|
||||
}
|
||||
|
||||
// Using a switch, the subject string has to be traversed at least twice (hash + comparison * N, where N is #strings hashed into the
|
||||
// same bucket). The optimization isn't better than an IF cascade when #switch-targets <= 2.
|
||||
override fun shouldOptimize() = hashAndSwitchLabels.size > 2
|
||||
// Using a switch, the subject string has to be traversed at least twice
|
||||
// (hash + comparison * N, where N is #strings hashed into the same bucket).
|
||||
// The optimization isn't better than an IF cascade when #switch-targets <= 2.
|
||||
//
|
||||
// Generate "optimized" version for @EnhancedNullability subject type
|
||||
// to model 1.0 behavior causing NPE in case of null value.
|
||||
// TODO make 'when' with String subject behavior consistent.
|
||||
// see:
|
||||
// box/when/stringOptimization/enhancedNullability.kt
|
||||
// box/when/stringOptimization/flexibleNullability.kt
|
||||
override fun shouldOptimize() =
|
||||
hashAndSwitchLabels.size > 2 ||
|
||||
subject.type.hasAnnotation(JvmAnnotationNames.ENHANCED_NULLABILITY_ANNOTATION) && hashAndSwitchLabels.isNotEmpty()
|
||||
|
||||
override fun genSwitch() {
|
||||
with(codegen) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
// WITH_RUNTIME
|
||||
// IGNORE_BACKEND: WASM
|
||||
|
||||
enum class EType {
|
||||
A
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
|
||||
// FILE: enhancedNullability.kt
|
||||
fun testEmpty() {
|
||||
when (J.nullString()) {
|
||||
}
|
||||
}
|
||||
|
||||
fun testSingle() {
|
||||
try {
|
||||
var q = "other"
|
||||
when (J.nullString()) {
|
||||
"a" -> q = "A"
|
||||
}
|
||||
throw Exception("Should throw NPE, got '$q'")
|
||||
} catch (e: NullPointerException) {
|
||||
}
|
||||
}
|
||||
|
||||
fun testElseOnly() {
|
||||
var q = "other"
|
||||
when (J.nullString()) {
|
||||
else -> q = "A"
|
||||
}
|
||||
if (q != "A") {
|
||||
throw Exception("Expected: 'A', got '$q'")
|
||||
}
|
||||
}
|
||||
|
||||
fun testSmall() {
|
||||
try {
|
||||
val q = when (J.nullString()) {
|
||||
"a" -> "A"
|
||||
else -> "other"
|
||||
}
|
||||
throw Exception("Should throw NPE, got '$q'")
|
||||
} catch (e: NullPointerException) {
|
||||
}
|
||||
}
|
||||
|
||||
fun testBigger() {
|
||||
try {
|
||||
val q = when (J.nullString()) {
|
||||
"a" -> "A"
|
||||
"b" -> "B"
|
||||
"c" -> "C"
|
||||
"d" -> "D"
|
||||
"e" -> "E"
|
||||
"f" -> "F"
|
||||
"g" -> "G"
|
||||
"h" -> "H"
|
||||
else -> "other"
|
||||
}
|
||||
throw Exception("Should throw NPE, got '$q'")
|
||||
} catch (e: NullPointerException) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
testEmpty()
|
||||
testSingle()
|
||||
testElseOnly()
|
||||
testSmall()
|
||||
testBigger()
|
||||
return "OK"
|
||||
}
|
||||
|
||||
// FILE: J.java
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class J {
|
||||
public static @NotNull String nullString() { return null; }
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_RUNTIME
|
||||
|
||||
// FILE: flexibleNullability.kt
|
||||
fun testEmpty() {
|
||||
when (J.nullString()) {
|
||||
}
|
||||
}
|
||||
|
||||
fun testSingle() {
|
||||
var q = "other"
|
||||
when (J.nullString()) {
|
||||
"a" -> q = "A"
|
||||
}
|
||||
if (q != "other") {
|
||||
throw Exception("Expected 'other', got '$q'")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun testElseOnly() {
|
||||
var q = "other"
|
||||
when (J.nullString()) {
|
||||
else -> q = "A"
|
||||
}
|
||||
if (q != "A") {
|
||||
throw Exception("Expected: 'A', got '$q'")
|
||||
}
|
||||
}
|
||||
|
||||
fun testSmall() {
|
||||
val q = when (J.nullString()) {
|
||||
"a" -> "A"
|
||||
else -> "other"
|
||||
}
|
||||
if (q != "other") {
|
||||
throw Exception("Expected 'other', got '$q'")
|
||||
}
|
||||
}
|
||||
|
||||
fun testBigger() {
|
||||
val q = when (J.nullString()) {
|
||||
"a" -> "A"
|
||||
"b" -> "B"
|
||||
"c" -> "C"
|
||||
"d" -> "D"
|
||||
"e" -> "E"
|
||||
"f" -> "F"
|
||||
"g" -> "G"
|
||||
"h" -> "H"
|
||||
else -> "other"
|
||||
}
|
||||
if (q != "other") {
|
||||
throw Exception("Expected 'other', got '$q'")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun box(): String {
|
||||
testEmpty()
|
||||
testSingle()
|
||||
testElseOnly()
|
||||
testSmall()
|
||||
testBigger()
|
||||
return "OK"
|
||||
}
|
||||
|
||||
// FILE: J.java
|
||||
public class J {
|
||||
public static String nullString() { return null; }
|
||||
}
|
||||
+12
@@ -42725,12 +42725,24 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/when/stringOptimization/duplicatingItemsSameHashCode3.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("enhancedNullability.kt")
|
||||
public void testEnhancedNullability() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/when/stringOptimization/enhancedNullability.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("expression.kt")
|
||||
public void testExpression() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/when/stringOptimization/expression.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("flexibleNullability.kt")
|
||||
public void testFlexibleNullability() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/when/stringOptimization/flexibleNullability.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nullability.kt")
|
||||
public void testNullability() throws Exception {
|
||||
|
||||
+12
@@ -42767,12 +42767,24 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/when/stringOptimization/duplicatingItemsSameHashCode3.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("enhancedNullability.kt")
|
||||
public void testEnhancedNullability() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/when/stringOptimization/enhancedNullability.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("expression.kt")
|
||||
public void testExpression() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/when/stringOptimization/expression.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("flexibleNullability.kt")
|
||||
public void testFlexibleNullability() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/when/stringOptimization/flexibleNullability.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nullability.kt")
|
||||
public void testNullability() throws Exception {
|
||||
|
||||
+10
@@ -34445,11 +34445,21 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/when/stringOptimization/duplicatingItemsSameHashCode3.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("enhancedNullability.kt")
|
||||
public void testEnhancedNullability() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/when/stringOptimization/enhancedNullability.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("expression.kt")
|
||||
public void testExpression() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/when/stringOptimization/expression.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("flexibleNullability.kt")
|
||||
public void testFlexibleNullability() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/when/stringOptimization/flexibleNullability.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("nullability.kt")
|
||||
public void testNullability() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/when/stringOptimization/nullability.kt");
|
||||
|
||||
Reference in New Issue
Block a user