From b821b26cfebc3afe17741e2f57635ca472831356 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Thu, 30 Sep 2021 03:01:42 +0200 Subject: [PATCH] JVM IR: do not try to optimize casts in TypeOperatorLowering In case the cast value is used as a receiver to a private method call, the cast is actually necessary, see KT-48927. Also, this optimization has backfired once already (see kt48659_identityEqualsWithCastToAny.kt). It seems that the best way to optimize these casts is not to generate them in the first place, and/or use bytecode postprocessing. Apparently the only kind of casts which need to be eliminated are those which occur on an inline class to its supertype. Otherwise the unsafe-coerce intrinsic is inserted at the incorrect place, and several tests fail (uncastInlineClassToAnyAndBack.kt, genericOverride.kt, classGenericOverride.kt). #KT-48927 Fixed --- .../codegen/FirBlackBoxCodegenTestGenerated.java | 12 ++++++++++++ .../backend/jvm/lower/TypeOperatorLowering.kt | 3 +-- .../kt48927_privateMethodOnDerivedCastToBase.kt | 9 +++++++++ .../uncastInlineClassToAnyAndBack.kt | 14 ++++++++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 12 ++++++++++++ .../codegen/IrBlackBoxCodegenTestGenerated.java | 12 ++++++++++++ .../codegen/LightAnalysisModeTestGenerated.java | 10 ++++++++++ .../semantics/IrJsCodegenBoxES6TestGenerated.java | 10 ++++++++++ .../ir/semantics/IrJsCodegenBoxTestGenerated.java | 10 ++++++++++ .../test/semantics/JsCodegenBoxTestGenerated.java | 10 ++++++++++ .../semantics/IrCodegenBoxWasmTestGenerated.java | 10 ++++++++++ 11 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 compiler/testData/codegen/box/casts/kt48927_privateMethodOnDerivedCastToBase.kt create mode 100644 compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/uncastInlineClassToAnyAndBack.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 ca1e99786fd..53affdcac67 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 @@ -4340,6 +4340,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/casts/kt22714.kt"); } + @Test + @TestMetadata("kt48927_privateMethodOnDerivedCastToBase.kt") + public void testKt48927_privateMethodOnDerivedCastToBase() throws Exception { + runTest("compiler/testData/codegen/box/casts/kt48927_privateMethodOnDerivedCastToBase.kt"); + } + @Test @TestMetadata("lambdaToUnitCast.kt") public void testLambdaToUnitCast() throws Exception { @@ -19905,6 +19911,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/relatedReturnTypes2b.kt"); } + @Test + @TestMetadata("uncastInlineClassToAnyAndBack.kt") + public void testUncastInlineClassToAnyAndBack() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/uncastInlineClassToAnyAndBack.kt"); + } + @Test @TestMetadata("unrelatedGenerics.kt") public void testUnrelatedGenerics() throws Exception { diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/TypeOperatorLowering.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/TypeOperatorLowering.kt index 470b4b38016..2d6a1a67eae 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/TypeOperatorLowering.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/TypeOperatorLowering.kt @@ -93,8 +93,7 @@ private class TypeOperatorLowering(private val context: JvmBackendContext) : Fil ) } } - // Do not optimize casts for values of primitive types because it can affect their identity and thus change behavior. - !argument.type.isPrimitiveType() && argument.type.isSubtypeOfClass(type.erasedUpperBound.symbol) -> + argument.type.isInlineClassType() && argument.type.isSubtypeOfClass(type.erasedUpperBound.symbol) -> argument else -> builder.irAs(argument, type) diff --git a/compiler/testData/codegen/box/casts/kt48927_privateMethodOnDerivedCastToBase.kt b/compiler/testData/codegen/box/casts/kt48927_privateMethodOnDerivedCastToBase.kt new file mode 100644 index 00000000000..7a9a73e1a0d --- /dev/null +++ b/compiler/testData/codegen/box/casts/kt48927_privateMethodOnDerivedCastToBase.kt @@ -0,0 +1,9 @@ +abstract class Base { + private fun test(): String = "OK" + + fun test(d: Derived): String = (d as Base).test() +} + +class Derived : Base() + +fun box(): String = Derived().test(Derived()) diff --git a/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/uncastInlineClassToAnyAndBack.kt b/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/uncastInlineClassToAnyAndBack.kt new file mode 100644 index 00000000000..d9c8c559050 --- /dev/null +++ b/compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/uncastInlineClassToAnyAndBack.kt @@ -0,0 +1,14 @@ +inline class X(val x: Any) + +interface IFoo { + fun foo(): T +} + +class TestX : IFoo { + override fun foo(): X = X("OK") +} + +fun box(): String { + val t: IFoo = TestX() + return ((t.foo() as Any) as X).x.toString() +} 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 a617be5481c..f6af8169730 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 @@ -4268,6 +4268,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/casts/kt22714.kt"); } + @Test + @TestMetadata("kt48927_privateMethodOnDerivedCastToBase.kt") + public void testKt48927_privateMethodOnDerivedCastToBase() throws Exception { + runTest("compiler/testData/codegen/box/casts/kt48927_privateMethodOnDerivedCastToBase.kt"); + } + @Test @TestMetadata("lambdaToUnitCast.kt") public void testLambdaToUnitCast() throws Exception { @@ -19773,6 +19779,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/relatedReturnTypes2b.kt"); } + @Test + @TestMetadata("uncastInlineClassToAnyAndBack.kt") + public void testUncastInlineClassToAnyAndBack() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/uncastInlineClassToAnyAndBack.kt"); + } + @Test @TestMetadata("unrelatedGenerics.kt") public void testUnrelatedGenerics() 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 584f431ff46..f32cffe0471 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 @@ -4340,6 +4340,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/casts/kt22714.kt"); } + @Test + @TestMetadata("kt48927_privateMethodOnDerivedCastToBase.kt") + public void testKt48927_privateMethodOnDerivedCastToBase() throws Exception { + runTest("compiler/testData/codegen/box/casts/kt48927_privateMethodOnDerivedCastToBase.kt"); + } + @Test @TestMetadata("lambdaToUnitCast.kt") public void testLambdaToUnitCast() throws Exception { @@ -19905,6 +19911,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/relatedReturnTypes2b.kt"); } + @Test + @TestMetadata("uncastInlineClassToAnyAndBack.kt") + public void testUncastInlineClassToAnyAndBack() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/uncastInlineClassToAnyAndBack.kt"); + } + @Test @TestMetadata("unrelatedGenerics.kt") public void testUnrelatedGenerics() 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 5b73d1b0dbf..96099ce444f 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -3729,6 +3729,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/casts/kt22714.kt"); } + @TestMetadata("kt48927_privateMethodOnDerivedCastToBase.kt") + public void testKt48927_privateMethodOnDerivedCastToBase() throws Exception { + runTest("compiler/testData/codegen/box/casts/kt48927_privateMethodOnDerivedCastToBase.kt"); + } + @TestMetadata("lambdaToUnitCast.kt") public void testLambdaToUnitCast() throws Exception { runTest("compiler/testData/codegen/box/casts/lambdaToUnitCast.kt"); @@ -16415,6 +16420,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/relatedReturnTypes2b.kt"); } + @TestMetadata("uncastInlineClassToAnyAndBack.kt") + public void testUncastInlineClassToAnyAndBack() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/uncastInlineClassToAnyAndBack.kt"); + } + @TestMetadata("unrelatedGenerics.kt") public void testUnrelatedGenerics() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/unrelatedGenerics.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java index b1303f6a644..06659fa26c3 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java @@ -2844,6 +2844,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes runTest("compiler/testData/codegen/box/casts/kt22714.kt"); } + @TestMetadata("kt48927_privateMethodOnDerivedCastToBase.kt") + public void testKt48927_privateMethodOnDerivedCastToBase() throws Exception { + runTest("compiler/testData/codegen/box/casts/kt48927_privateMethodOnDerivedCastToBase.kt"); + } + @TestMetadata("lambdaToUnitCast.kt") public void testLambdaToUnitCast() throws Exception { runTest("compiler/testData/codegen/box/casts/lambdaToUnitCast.kt"); @@ -14399,6 +14404,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/relatedReturnTypes2b.kt"); } + @TestMetadata("uncastInlineClassToAnyAndBack.kt") + public void testUncastInlineClassToAnyAndBack() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/uncastInlineClassToAnyAndBack.kt"); + } + @TestMetadata("unrelatedGenerics.kt") public void testUnrelatedGenerics() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/unrelatedGenerics.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index 7e51c515d8d..03348dac180 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -2844,6 +2844,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/casts/kt22714.kt"); } + @TestMetadata("kt48927_privateMethodOnDerivedCastToBase.kt") + public void testKt48927_privateMethodOnDerivedCastToBase() throws Exception { + runTest("compiler/testData/codegen/box/casts/kt48927_privateMethodOnDerivedCastToBase.kt"); + } + @TestMetadata("lambdaToUnitCast.kt") public void testLambdaToUnitCast() throws Exception { runTest("compiler/testData/codegen/box/casts/lambdaToUnitCast.kt"); @@ -13805,6 +13810,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/relatedReturnTypes2b.kt"); } + @TestMetadata("uncastInlineClassToAnyAndBack.kt") + public void testUncastInlineClassToAnyAndBack() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/uncastInlineClassToAnyAndBack.kt"); + } + @TestMetadata("unrelatedGenerics.kt") public void testUnrelatedGenerics() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/unrelatedGenerics.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 6359060c950..54ddd6ecbfa 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -2809,6 +2809,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/casts/kt22714.kt"); } + @TestMetadata("kt48927_privateMethodOnDerivedCastToBase.kt") + public void testKt48927_privateMethodOnDerivedCastToBase() throws Exception { + runTest("compiler/testData/codegen/box/casts/kt48927_privateMethodOnDerivedCastToBase.kt"); + } + @TestMetadata("lambdaToUnitCast.kt") public void testLambdaToUnitCast() throws Exception { runTest("compiler/testData/codegen/box/casts/lambdaToUnitCast.kt"); @@ -13835,6 +13840,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/relatedReturnTypes2b.kt"); } + @TestMetadata("uncastInlineClassToAnyAndBack.kt") + public void testUncastInlineClassToAnyAndBack() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/uncastInlineClassToAnyAndBack.kt"); + } + @TestMetadata("unrelatedGenerics.kt") public void testUnrelatedGenerics() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/unrelatedGenerics.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java index a8ce3dfa852..7a43e61ad60 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java @@ -2349,6 +2349,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest runTest("compiler/testData/codegen/box/casts/kt22714.kt"); } + @TestMetadata("kt48927_privateMethodOnDerivedCastToBase.kt") + public void testKt48927_privateMethodOnDerivedCastToBase() throws Exception { + runTest("compiler/testData/codegen/box/casts/kt48927_privateMethodOnDerivedCastToBase.kt"); + } + @TestMetadata("lambdaToUnitCast.kt") public void testLambdaToUnitCast() throws Exception { runTest("compiler/testData/codegen/box/casts/lambdaToUnitCast.kt"); @@ -8684,6 +8689,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/relatedReturnTypes2b.kt"); } + @TestMetadata("uncastInlineClassToAnyAndBack.kt") + public void testUncastInlineClassToAnyAndBack() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/uncastInlineClassToAnyAndBack.kt"); + } + @TestMetadata("unrelatedGenerics.kt") public void testUnrelatedGenerics() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/boxReturnValueOnOverride/unrelatedGenerics.kt");