diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java index 74bad09c0f2..ac9c1a41863 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ExpressionCodegen.java @@ -4431,9 +4431,17 @@ The "returned" value of try expression with no finally is either the last expres StackValue value = genQualified(receiver, left); + KotlinType leftKotlinType = value.kotlinType; + Type boxedLeftType; + if (leftKotlinType != null && InlineClassesUtilsKt.isInlineClassType(leftKotlinType)) { + boxedLeftType = typeMapper.mapTypeAsDeclaration(leftKotlinType); + } else { + boxedLeftType = boxType(value.type); + } + Type boxedRightType = boxType(typeMapper.mapTypeAsDeclaration(rightKotlinType)); return StackValue.operation(boxedRightType, rightKotlinType, v -> { - value.put(boxType(value.type), value.kotlinType, v); + value.put(boxedLeftType, value.kotlinType, v); if (value.type == Type.VOID_TYPE) { StackValue.putUnitInstance(v); diff --git a/compiler/testData/codegen/box/inlineClasses/inlineClassesCheckCast.kt b/compiler/testData/codegen/box/inlineClasses/inlineClassesCheckCast.kt new file mode 100644 index 00000000000..768ca4ca0ee --- /dev/null +++ b/compiler/testData/codegen/box/inlineClasses/inlineClassesCheckCast.kt @@ -0,0 +1,48 @@ +// !LANGUAGE: +InlineClasses + +inline class AsAny(val x: Any?) +inline class AsInt(val x: Int) + +inline fun Any?.checkcast(): T = this as T + +object Reference { + fun transform(a: AsAny): AsAny = a as AsAny + fun transformNullable(a: AsAny?): AsAny = a as AsAny + fun transformToNullable(a: AsAny): AsAny? = a as AsAny + fun transformToNullableTarget(a: AsAny): AsAny? = a as AsAny? + fun transformNullableToNullableTarget(a: AsAny?): AsAny? = a as AsAny? +} + +object Primitive { + fun transform(a: AsInt): AsInt = a as AsInt + fun transformNullable(a: AsInt?): AsInt = a as AsInt + fun transformToNullable(a: AsInt): AsInt? = a as AsInt + fun transformToNullableTarget(a: AsInt): AsInt? = a as AsInt? + fun transformNullableToNullableTarget(a: AsInt?): AsInt? = a as AsInt? +} + +fun box(): String { + val a = AsAny(42) + val b1 = Reference.transform(a) + val b2 = Reference.transformNullable(a) + val b3 = Reference.transformToNullable(a) + val b4 = Reference.transformToNullableTarget(a) + val b5 = Reference.transformNullableToNullableTarget(a) + val b6 = Reference.transformNullableToNullableTarget(null) + + val b7 = a.checkcast>() + if (b7.x != a.x) return "Fail 1" + + val c = AsInt(42) + val d1 = Primitive.transform(c) + val d2 = Primitive.transformNullable(c) + val d3 = Primitive.transformToNullable(c) + val d4 = Primitive.transformToNullableTarget(c) + val d5 = Primitive.transformNullableToNullableTarget(c) + val d6 = Primitive.transformNullableToNullableTarget(null) + + val d7 = c.checkcast() + if (d7.x != c.x) return "Fail 2" + + return "OK" +} \ No newline at end of file diff --git a/compiler/testData/codegen/bytecodeText/inlineClasses/noBoxingOnCastOperations.kt b/compiler/testData/codegen/bytecodeText/inlineClasses/noBoxingOnCastOperations.kt new file mode 100644 index 00000000000..12759de7fd5 --- /dev/null +++ b/compiler/testData/codegen/bytecodeText/inlineClasses/noBoxingOnCastOperations.kt @@ -0,0 +1,30 @@ +// !LANGUAGE: +InlineClasses + +// FILE: util.kt + +inline class AsAny(val x: Any?) +inline class AsInt(val x: Int) + +// FILE: Reference.kt + +fun transform(a: AsAny): AsAny = a as AsAny +fun transformNullable(a: AsAny?): AsAny = a as AsAny // unbox +fun transformToNullable(a: AsAny): AsAny? = a as AsAny // box +fun transformToNullableTarget(a: AsAny): AsAny? = a as AsAny? // box +fun transformNullableToNullableTarget(a: AsAny?): AsAny? = a as AsAny? + +// FILE: Primitive.kt + +fun transform(a: AsInt): AsInt = a as AsInt +fun transformNullable(a: AsInt?): AsInt = a as AsInt // unbox +fun transformToNullable(a: AsInt): AsInt? = a as AsInt // box +fun transformToNullableTarget(a: AsInt): AsInt? = a as AsInt? // box +fun transformNullableToNullableTarget(a: AsInt?): AsInt? = a as AsInt? + +// @ReferenceKt.class: +// 2 INVOKESTATIC AsAny\$Erased.box +// 1 INVOKEVIRTUAL AsAny.unbox + +// @PrimitiveKt.class: +// 2 INVOKESTATIC AsInt\$Erased.box +// 1 INVOKEVIRTUAL AsInt.unbox diff --git a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 521dc72e6cb..d3cfbd7b1dd 100644 --- a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -10978,6 +10978,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/inlineClasses/inlineClassImplementsCollection.kt"); } + @TestMetadata("inlineClassesCheckCast.kt") + public void testInlineClassesCheckCast() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/inlineClassesCheckCast.kt"); + } + @TestMetadata("inlineFunctionInsideInlineClass.kt") public void testInlineFunctionInsideInlineClass() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/inlineFunctionInsideInlineClass.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 3cf3fd5af1e..4caeb9a986a 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -10978,6 +10978,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/inlineClasses/inlineClassImplementsCollection.kt"); } + @TestMetadata("inlineClassesCheckCast.kt") + public void testInlineClassesCheckCast() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/inlineClassesCheckCast.kt"); + } + @TestMetadata("inlineFunctionInsideInlineClass.kt") public void testInlineFunctionInsideInlineClass() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/inlineFunctionInsideInlineClass.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java index 913283db80c..afaf9539b61 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BytecodeTextTestGenerated.java @@ -2060,6 +2060,11 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest { runTest("compiler/testData/codegen/bytecodeText/inlineClasses/noAssertionsForInlineClassesBasedOnNullableTypes.kt"); } + @TestMetadata("noBoxingOnCastOperations.kt") + public void testNoBoxingOnCastOperations() throws Exception { + runTest("compiler/testData/codegen/bytecodeText/inlineClasses/noBoxingOnCastOperations.kt"); + } + @TestMetadata("noBoxingOperationsOnNonTrivialSpread.kt") public void testNoBoxingOperationsOnNonTrivialSpread() throws Exception { runTest("compiler/testData/codegen/bytecodeText/inlineClasses/noBoxingOperationsOnNonTrivialSpread.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 7a6c587f7c4..293e6265281 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -10978,6 +10978,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/inlineClasses/inlineClassImplementsCollection.kt"); } + @TestMetadata("inlineClassesCheckCast.kt") + public void testInlineClassesCheckCast() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/inlineClassesCheckCast.kt"); + } + @TestMetadata("inlineFunctionInsideInlineClass.kt") public void testInlineFunctionInsideInlineClass() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/inlineFunctionInsideInlineClass.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java index 629ab3f7995..f210e27c4aa 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrJsCodegenBoxTestGenerated.java @@ -9648,6 +9648,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/inlineClasses/inlineClassAsLastExpressionInInLambda.kt"); } + @TestMetadata("inlineClassesCheckCast.kt") + public void testInlineClassesCheckCast() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/inlineClassesCheckCast.kt"); + } + @TestMetadata("inlineFunctionInsideInlineClass.kt") public void testInlineFunctionInsideInlineClass() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/inlineFunctionInsideInlineClass.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 353e2734bf8..2abe363a629 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -9648,6 +9648,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/inlineClasses/inlineClassAsLastExpressionInInLambda.kt"); } + @TestMetadata("inlineClassesCheckCast.kt") + public void testInlineClassesCheckCast() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/inlineClassesCheckCast.kt"); + } + @TestMetadata("inlineFunctionInsideInlineClass.kt") public void testInlineFunctionInsideInlineClass() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/inlineFunctionInsideInlineClass.kt");