diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/OptimizationBasicInterpreter.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/OptimizationBasicInterpreter.java index 8c52059e38a..9702948c48d 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/OptimizationBasicInterpreter.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/common/OptimizationBasicInterpreter.java @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.codegen.optimization.common; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.codegen.AsmUtil; +import org.jetbrains.kotlin.resolve.jvm.AsmTypes; import org.jetbrains.org.objectweb.asm.Handle; import org.jetbrains.org.objectweb.asm.Opcodes; import org.jetbrains.org.objectweb.asm.Type; @@ -152,13 +153,6 @@ public class OptimizationBasicInterpreter extends Interpreter implem @NotNull BasicValue value1, @NotNull BasicValue value2 ) throws AnalyzerException { - if (insn.getOpcode() == Opcodes.AALOAD) { - Type arrayType = value1.getType(); - if (arrayType != null && arrayType.getSort() == Type.ARRAY) { - return new StrictBasicValue(AsmUtil.correctElementType(arrayType)); - } - } - switch (insn.getOpcode()) { case IALOAD: case BALOAD: @@ -204,7 +198,13 @@ public class OptimizationBasicInterpreter extends Interpreter implem case DREM: return StrictBasicValue.DOUBLE_VALUE; case AALOAD: - return StrictBasicValue.NULL_VALUE; + Type arrayType = value1.getType(); + if (arrayType != null && arrayType.getSort() == Type.ARRAY) { + return new StrictBasicValue(AsmUtil.correctElementType(arrayType)); + } + else { + return StrictBasicValue.NULL_VALUE; + } case LCMP: case FCMPL: case FCMPG: @@ -359,13 +359,11 @@ public class OptimizationBasicInterpreter extends Interpreter implem return StrictBasicValue.UNINITIALIZED_VALUE; } - // if merge of two references then `lub` is java/lang/Object - // arrays also are BasicValues with reference type's if (isReference(v) && isReference(w)) { if (v == NULL_VALUE) return newValue(w.getType()); if (w == NULL_VALUE) return newValue(v.getType()); - return StrictBasicValue.REFERENCE_VALUE; + return mergeReferenceTypes(w.getType(), v.getType()); } // if merge of something can be stored in int var (int, char, boolean, byte, character) @@ -380,4 +378,35 @@ public class OptimizationBasicInterpreter extends Interpreter implem private static boolean isReference(@NotNull BasicValue v) { return v.getType().getSort() == Type.OBJECT || v.getType().getSort() == Type.ARRAY; } + + // Merge reference types, keeping track of array dimensions. + // See also org.jetbrains.org.objectweb.asm.Frame.merge. + // It's assumed that types a and b are not equal when calling this method. + private BasicValue mergeReferenceTypes(@NotNull Type a, @NotNull Type b) { + // Find out the minimal array dimension of both types. + int arrayDimensions = 0; + while (a.getSort() == Type.ARRAY && b.getSort() == Type.ARRAY) { + a = AsmUtil.correctElementType(a); + b = AsmUtil.correctElementType(b); + arrayDimensions++; + } + // Either of the two types is not an array -> result is j/l/Object. + if (arrayDimensions == 0) return REFERENCE_VALUE; + + // Both of the types are arrays, and element type of one or both of them is primitive -> + // result is array of j/l/Object with one fewer dimension. E.g. + // merge([I, [Lj/l/Object;) = Lj/l/Object; + // merge([I, [S) = Lj/l/Object; + // merge([[I, [[Lj/l/Object;) = [Lj/l/Object; + if (AsmUtil.isPrimitive(a) || AsmUtil.isPrimitive(b)) { + arrayDimensions--; + } + + // Result is array of j/l/Object with the computed dimension. + StringBuilder result = new StringBuilder(); + while (arrayDimensions-- > 0) result.append("["); + result.append(AsmTypes.OBJECT_TYPE.getDescriptor()); + return newValue(Type.getType(result.toString())); + } + } diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index 7bd62468f9a..113d874f787 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -4829,6 +4829,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/casts/kt54707.kt"); } + @Test + @TestMetadata("kt54802.kt") + public void testKt54802() throws Exception { + runTest("compiler/testData/codegen/box/casts/kt54802.kt"); + } + @Test @TestMetadata("lambdaToUnitCast.kt") public void testLambdaToUnitCast() throws Exception { diff --git a/compiler/testData/codegen/box/casts/kt54707.kt b/compiler/testData/codegen/box/casts/kt54707.kt index bf0f9692a15..74a48eb5927 100644 --- a/compiler/testData/codegen/box/casts/kt54707.kt +++ b/compiler/testData/codegen/box/casts/kt54707.kt @@ -1,6 +1,3 @@ -// IGNORE_BACKEND: JVM -// IGNORE_LIGHT_ANALYSIS - fun box(): String = g(arrayOf("O")) @@ -12,4 +9,3 @@ inline fun Array.f(lambda: (T) -> T): T = inline fun Array?.orEmpty0(): Array = this ?: (arrayOfNulls(0) as Array) - diff --git a/compiler/testData/codegen/box/casts/kt54802.kt b/compiler/testData/codegen/box/casts/kt54802.kt new file mode 100644 index 00000000000..dc66bf42438 --- /dev/null +++ b/compiler/testData/codegen/box/casts/kt54802.kt @@ -0,0 +1,14 @@ +class K { + val x: String = "OK" +} + +inline fun Array.ifEmpty(body: () -> Array): Array = + if (size == 0) body() else this + +inline fun Array.f(p: (T) -> String): String = + p(this[0]) + +fun box(): String = + emptyArray() + .ifEmpty { arrayOf(K()) } + .f(K::x) diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index 30900393c61..5c036de2dec 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -4697,6 +4697,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/casts/kt54707.kt"); } + @Test + @TestMetadata("kt54802.kt") + public void testKt54802() throws Exception { + runTest("compiler/testData/codegen/box/casts/kt54802.kt"); + } + @Test @TestMetadata("lambdaToUnitCast.kt") public void testLambdaToUnitCast() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index 75bc16a75fc..4219923fe19 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -4829,6 +4829,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/casts/kt54707.kt"); } + @Test + @TestMetadata("kt54802.kt") + public void testKt54802() throws Exception { + runTest("compiler/testData/codegen/box/casts/kt54802.kt"); + } + @Test @TestMetadata("lambdaToUnitCast.kt") public void testLambdaToUnitCast() throws Exception { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 7373b56ec91..0ebf8a39344 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -3958,11 +3958,6 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) public static class Casts extends AbstractLightAnalysisModeTest { - @TestMetadata("kt54707.kt") - public void ignoreKt54707() throws Exception { - runTest("compiler/testData/codegen/box/casts/kt54707.kt"); - } - private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath); } @@ -4096,6 +4091,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/casts/kt54581.kt"); } + @TestMetadata("kt54707.kt") + public void testKt54707() throws Exception { + runTest("compiler/testData/codegen/box/casts/kt54707.kt"); + } + + @TestMetadata("kt54802.kt") + public void testKt54802() throws Exception { + runTest("compiler/testData/codegen/box/casts/kt54802.kt"); + } + @TestMetadata("lambdaToUnitCast.kt") public void testLambdaToUnitCast() throws Exception { runTest("compiler/testData/codegen/box/casts/lambdaToUnitCast.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsCodegenBoxTestGenerated.java index 7638cf0addb..9d4f63b86a6 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsCodegenBoxTestGenerated.java @@ -3419,6 +3419,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/casts/kt54707.kt"); } + @Test + @TestMetadata("kt54802.kt") + public void testKt54802() throws Exception { + runTest("compiler/testData/codegen/box/casts/kt54802.kt"); + } + @Test @TestMetadata("lambdaToUnitCast.kt") public void testLambdaToUnitCast() throws Exception { diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java index 159f75443f5..4ee5cc7abad 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java @@ -3479,6 +3479,12 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/casts/kt54707.kt"); } + @Test + @TestMetadata("kt54802.kt") + public void testKt54802() throws Exception { + runTest("compiler/testData/codegen/box/casts/kt54802.kt"); + } + @Test @TestMetadata("lambdaToUnitCast.kt") public void testLambdaToUnitCast() throws Exception { diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/testOld/wasm/semantics/IrCodegenBoxWasmTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/testOld/wasm/semantics/IrCodegenBoxWasmTestGenerated.java index f27925f1c6f..cc5138f6912 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/testOld/wasm/semantics/IrCodegenBoxWasmTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/testOld/wasm/semantics/IrCodegenBoxWasmTestGenerated.java @@ -3071,6 +3071,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest runTest("compiler/testData/codegen/box/casts/kt54707.kt"); } + @TestMetadata("kt54802.kt") + public void testKt54802() throws Exception { + runTest("compiler/testData/codegen/box/casts/kt54802.kt"); + } + @TestMetadata("lambdaToUnitCast.kt") public void testLambdaToUnitCast() throws Exception { runTest("compiler/testData/codegen/box/casts/lambdaToUnitCast.kt"); diff --git a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java index c85f652f30a..fdc6e2eb858 100644 --- a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java +++ b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java @@ -3553,6 +3553,12 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest runTest("compiler/testData/codegen/box/casts/kt54707.kt"); } + @Test + @TestMetadata("kt54802.kt") + public void testKt54802() throws Exception { + runTest("compiler/testData/codegen/box/casts/kt54802.kt"); + } + @Test @TestMetadata("lambdaToUnitCast.kt") public void testLambdaToUnitCast() throws Exception {