From 0eadf35132736101cfc16aa4ab905fd4dee30152 Mon Sep 17 00:00:00 2001 From: Xin Wang Date: Tue, 23 Aug 2022 22:47:39 +0800 Subject: [PATCH] Inline: Fix operand stack type verify error This is a proposal to fix KT-49364. Operand stack type verification happens before `checkcast` is executed. When we implicitly cast an inline class to a non-inline type, if type of stack value is not subtype of the target, then coercing is necessary. --- .../FirBlackBoxCodegenTestGenerated.java | 6 ++++++ .../backend/jvm/codegen/PromisedValue.kt | 7 +++++++ .../implicitCastToNonValueClassType.kt | 19 +++++++++++++++++++ .../IrBlackBoxCodegenTestGenerated.java | 6 ++++++ 4 files changed, 38 insertions(+) create mode 100644 compiler/testData/codegen/box/inlineClasses/implicitCastToNonValueClassType.kt 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 58a6067fac0..7b7bc940aef 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 @@ -21287,6 +21287,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/inlineClasses/genericVararg2ndConstructor.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal()); } + @Test + @TestMetadata("implicitCastToNonValueClassType.kt") + public void testImplicitCastToNonValueClassType() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/implicitCastToNonValueClassType.kt"); + } + @Test @TestMetadata("initBlock.kt") public void testInitBlock() throws Exception { diff --git a/compiler/ir/backend.jvm/codegen/src/org/jetbrains/kotlin/backend/jvm/codegen/PromisedValue.kt b/compiler/ir/backend.jvm/codegen/src/org/jetbrains/kotlin/backend/jvm/codegen/PromisedValue.kt index 6d668abfe87..f99ab3bcf05 100644 --- a/compiler/ir/backend.jvm/codegen/src/org/jetbrains/kotlin/backend/jvm/codegen/PromisedValue.kt +++ b/compiler/ir/backend.jvm/codegen/src/org/jetbrains/kotlin/backend/jvm/codegen/PromisedValue.kt @@ -38,6 +38,13 @@ abstract class PromisedValue(val codegen: ExpressionCodegen, val type: Type, val if (isFromTypeUnboxed && !isToTypeUnboxed) { val boxed = typeMapper.mapType(erasedSourceType, TypeMappingMode.CLASS_DECLARATION) StackValue.boxInlineClass(type, boxed, erasedSourceType.isNullable(), mv) + + if (typeMapper.mapType(erasedTargetType) == target) { + if (!erasedSourceType.isSubtypeOf(erasedTargetType, codegen.context.typeSystem)) { + StackValue.coerce(boxed, target, mv, false) + } + } + return } if (!isFromTypeUnboxed && isToTypeUnboxed) { diff --git a/compiler/testData/codegen/box/inlineClasses/implicitCastToNonValueClassType.kt b/compiler/testData/codegen/box/inlineClasses/implicitCastToNonValueClassType.kt new file mode 100644 index 00000000000..f35c2fc9d6f --- /dev/null +++ b/compiler/testData/codegen/box/inlineClasses/implicitCastToNonValueClassType.kt @@ -0,0 +1,19 @@ +// TARGET_BACKEND: JVM_IR +// WITH_STDLIB + +fun box(): String { + try { + val a:ULong = 1u + a as Int + func(a) + } catch (e: ClassCastException) { + return "OK" + } + return "FAIL" +} + +fun func(para: Int) {} + +// CHECK_BYTECODE_TEXT +// 1 CHECKCAST java/lang/Integer +// 1 L2I \ No newline at end of file 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 8a8d7072f71..d00d3bfa133 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 @@ -21287,6 +21287,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/inlineClasses/genericVararg2ndConstructor.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal()); } + @Test + @TestMetadata("implicitCastToNonValueClassType.kt") + public void testImplicitCastToNonValueClassType() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/implicitCastToNonValueClassType.kt"); + } + @Test @TestMetadata("initBlock.kt") public void testInitBlock() throws Exception {