From 8f23fc54a463891768dd1a2c07127e1785895736 Mon Sep 17 00:00:00 2001 From: Ilmir Usmanov Date: Fri, 11 Feb 2022 05:34:50 +0100 Subject: [PATCH] Mangle bridges if its return type is not inline #KT-51235 Fixed --- .../FirBlackBoxCodegenTestGenerated.java | 6 +++ .../backend/jvm/lower/BridgeLowering.kt | 24 ++++++--- .../inlineClasses/overrideReturnNothing.kt | 49 +++++++++++++++++++ .../inlineClasses/overrideReturnNothing.txt | 48 ++++++++++++++++++ .../codegen/BlackBoxCodegenTestGenerated.java | 6 +++ .../IrBlackBoxCodegenTestGenerated.java | 6 +++ .../LightAnalysisModeTestGenerated.java | 5 ++ .../js/test/JsCodegenBoxTestGenerated.java | 6 +++ .../test/ir/IrJsCodegenBoxTestGenerated.java | 6 +++ .../IrCodegenBoxWasmTestGenerated.java | 5 ++ .../NativeCodegenBoxTestGenerated.java | 6 +++ 11 files changed, 161 insertions(+), 6 deletions(-) create mode 100644 compiler/testData/codegen/box/inlineClasses/overrideReturnNothing.kt create mode 100644 compiler/testData/codegen/box/inlineClasses/overrideReturnNothing.txt 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 5a44ffa8b62..79294dec68f 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 @@ -20491,6 +20491,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/inlineClasses/nullableWrapperEquality.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal()); } + @Test + @TestMetadata("overrideReturnNothing.kt") + public void testOverrideReturnNothing() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/overrideReturnNothing.kt"); + } + @Test @TestMetadata("overridingFunCallingPrivateFun.kt") public void testOverridingFunCallingPrivateFun() throws Exception { diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/BridgeLowering.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/BridgeLowering.kt index 38f2571ed1b..f372b013e50 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/BridgeLowering.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/BridgeLowering.kt @@ -15,9 +15,7 @@ import org.jetbrains.kotlin.backend.common.lower.VariableRemapper import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.common.lower.irNot import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase -import org.jetbrains.kotlin.backend.jvm.JvmBackendContext -import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin -import org.jetbrains.kotlin.backend.jvm.SpecialBridge +import org.jetbrains.kotlin.backend.jvm.* import org.jetbrains.kotlin.backend.jvm.ir.* import org.jetbrains.kotlin.codegen.AsmUtil import org.jetbrains.kotlin.descriptors.DescriptorVisibilities @@ -345,10 +343,14 @@ internal class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass for (override in irFunction.allOverridden()) { if (override.isFakeOverride) continue - val signature = override.jvmMethod + val target = override.mangleFunctionIfNeeded() + + val signature = target.jvmMethod if (targetMethod != signature && signature !in blacklist) { - val bridge = generated.getOrPut(signature) { Bridge(override, signature) } - bridge.overriddenSymbols += override.symbol + val bridge = generated.getOrPut(signature) { + Bridge(target, signature) + } + bridge.overriddenSymbols += target.symbol } } @@ -360,6 +362,16 @@ internal class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass .forEach { irClass.addBridge(it, bridgeTarget) } } + private fun IrSimpleFunction.mangleFunctionIfNeeded(): IrSimpleFunction { + if (!hasMangledReturnType && !hasMangledParameters) return this + val replacement = context.inlineClassReplacements.getReplacementFunction(this) ?: return this + if (name.asString().substringAfterLast('-') == replacement.name.asString().substringAfterLast('-')) { + // function is already mangled + return this + } + return replacement + } + private fun IrSimpleFunction.isClashingWithPotentialBridge(name: Name, signature: Method): Boolean = (!this.isFakeOverride || this.modality == Modality.FINAL) && this.name == name && this.jvmMethod == signature diff --git a/compiler/testData/codegen/box/inlineClasses/overrideReturnNothing.kt b/compiler/testData/codegen/box/inlineClasses/overrideReturnNothing.kt new file mode 100644 index 00000000000..60d3faeb899 --- /dev/null +++ b/compiler/testData/codegen/box/inlineClasses/overrideReturnNothing.kt @@ -0,0 +1,49 @@ +// WITH_STDLIB +// CHECK_BYTECODE_LISTING +// IGNORE_BACKEND: JS, JS_IR, WASM +// TODO: Fir2Ir generates overrides as finals. +// IGNORE_BACKEND_FIR: JVM_IR + +@JvmInline +value class Inlined(val value: Int) + +sealed interface A { + val property: Inlined? + + val property2: Inlined + + fun foo(): Inlined? + + fun foo2(): Inlined +} + +class B : A { + override val property: Nothing? = null + + override val property2: Nothing + get() = error("OK") + + override fun foo(): Nothing? = null + + override fun foo2(): Nothing = error("OK") +} + +fun box(): String { + val a: A = B() + if (a.property != null) return "FAIL 1" + if (a.foo() != null) return "FAIL 2" + try { + a.property2 + return "FAIL 3" + } catch (e: IllegalStateException) { + if (e.message != "OK") return "FAIL 4: ${e.message}" + } + try { + a.foo2() + return "FAIL 5" + } catch (e: IllegalStateException) { + if (e.message != "OK") return "FAIL 6: ${e.message}" + } + return "OK" +} + diff --git a/compiler/testData/codegen/box/inlineClasses/overrideReturnNothing.txt b/compiler/testData/codegen/box/inlineClasses/overrideReturnNothing.txt new file mode 100644 index 00000000000..fb1da85516e --- /dev/null +++ b/compiler/testData/codegen/box/inlineClasses/overrideReturnNothing.txt @@ -0,0 +1,48 @@ +@kotlin.Metadata +public interface A { + // source: 'overrideReturnNothing.kt' + public abstract @org.jetbrains.annotations.Nullable method foo-wSRmS7I(): Inlined + public abstract method foo2-yXoPhBc(): int + public abstract @org.jetbrains.annotations.Nullable method getProperty-wSRmS7I(): Inlined + public abstract method getProperty2-yXoPhBc(): int +} + +@kotlin.Metadata +public final class B { + // source: 'overrideReturnNothing.kt' + private final @org.jetbrains.annotations.Nullable field property: java.lang.Void + public method (): void + public @org.jetbrains.annotations.Nullable method foo(): java.lang.Void + public synthetic bridge method foo-wSRmS7I(): Inlined + public @org.jetbrains.annotations.NotNull method foo2(): java.lang.Void + public synthetic bridge method foo2-yXoPhBc(): int + public @org.jetbrains.annotations.Nullable method getProperty(): java.lang.Void + public synthetic bridge method getProperty-wSRmS7I(): Inlined + public @org.jetbrains.annotations.NotNull method getProperty2(): java.lang.Void + public synthetic bridge method getProperty2-yXoPhBc(): int +} + +@kotlin.jvm.JvmInline +@kotlin.Metadata +public final class Inlined { + // source: 'overrideReturnNothing.kt' + private final field value: int + private synthetic method (p0: int): void + public synthetic final static method box-impl(p0: int): Inlined + public static method constructor-impl(p0: int): int + public method equals(p0: java.lang.Object): boolean + public static method equals-impl(p0: int, p1: java.lang.Object): boolean + public final static method equals-impl0(p0: int, p1: int): boolean + public final method getValue(): int + public method hashCode(): int + public static method hashCode-impl(p0: int): int + public method toString(): java.lang.String + public static method toString-impl(p0: int): java.lang.String + public synthetic final method unbox-impl(): int +} + +@kotlin.Metadata +public final class OverrideReturnNothingKt { + // source: 'overrideReturnNothing.kt' + public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String +} 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 e4ea84cfeef..0bdee914266 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 @@ -20071,6 +20071,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/inlineClasses/nullableWrapperEquality.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal()); } + @Test + @TestMetadata("overrideReturnNothing.kt") + public void testOverrideReturnNothing() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/overrideReturnNothing.kt"); + } + @Test @TestMetadata("overridingFunCallingPrivateFun.kt") public void testOverridingFunCallingPrivateFun() 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 e892ccea72e..5b939950a17 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 @@ -20491,6 +20491,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/inlineClasses/nullableWrapperEquality.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal()); } + @Test + @TestMetadata("overrideReturnNothing.kt") + public void testOverrideReturnNothing() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/overrideReturnNothing.kt"); + } + @Test @TestMetadata("overridingFunCallingPrivateFun.kt") public void testOverridingFunCallingPrivateFun() 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 b85a73279b7..7fa8a0f30dc 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -16715,6 +16715,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/inlineClasses/nullableWrapperEquality.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal()); } + @TestMetadata("overrideReturnNothing.kt") + public void testOverrideReturnNothing() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/overrideReturnNothing.kt"); + } + @TestMetadata("overridingFunCallingPrivateFun.kt") public void testOverridingFunCallingPrivateFun() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/overridingFunCallingPrivateFun.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal()); 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 abc8bb36e50..a065cb3b51f 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 @@ -15753,6 +15753,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/inlineClasses/nullableWrapperEquality.kt", TransformersFunctions.getRemoveOptionalJvmInlineAnnotation()); } + @Test + @TestMetadata("overrideReturnNothing.kt") + public void testOverrideReturnNothing() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/overrideReturnNothing.kt"); + } + @Test @TestMetadata("overridingFunCallingPrivateFun.kt") public void testOverridingFunCallingPrivateFun() 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 b9897c4aea5..e6182b87dee 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 @@ -15717,6 +15717,12 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/inlineClasses/nullableWrapperEquality.kt", TransformersFunctions.getRemoveOptionalJvmInlineAnnotation()); } + @Test + @TestMetadata("overrideReturnNothing.kt") + public void testOverrideReturnNothing() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/overrideReturnNothing.kt"); + } + @Test @TestMetadata("overridingFunCallingPrivateFun.kt") public void testOverridingFunCallingPrivateFun() 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 47ca59b2db2..761e8131c23 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 @@ -13242,6 +13242,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest runTest("compiler/testData/codegen/box/inlineClasses/nullableWrapperEquality.kt", TransformersFunctions.getRemoveOptionalJvmInlineAnnotation()); } + @TestMetadata("overrideReturnNothing.kt") + public void testOverrideReturnNothing() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/overrideReturnNothing.kt"); + } + @TestMetadata("overridingFunCallingPrivateFun.kt") public void testOverridingFunCallingPrivateFun() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/overridingFunCallingPrivateFun.kt", TransformersFunctions.getRemoveOptionalJvmInlineAnnotation()); 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 6144da961c9..b4f860a3393 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 @@ -17089,6 +17089,12 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest runTest("compiler/testData/codegen/box/inlineClasses/nullableWrapperEquality.kt"); } + @Test + @TestMetadata("overrideReturnNothing.kt") + public void testOverrideReturnNothing() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/overrideReturnNothing.kt"); + } + @Test @TestMetadata("overridingFunCallingPrivateFun.kt") public void testOverridingFunCallingPrivateFun() throws Exception {