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 fc484910e84..1ba6e60789d 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 @@ -21475,6 +21475,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/inlineClasses/kt51672.kt"); } + @Test + @TestMetadata("kt52394.kt") + public void testKt52394() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/kt52394.kt"); + } + @Test @TestMetadata("mangledDefaultParameterFunction.kt") public void testMangledDefaultParameterFunction() 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 f372b013e50..ca3cffe8402 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 @@ -343,14 +343,12 @@ internal class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass for (override in irFunction.allOverridden()) { if (override.isFakeOverride) continue - val target = override.mangleFunctionIfNeeded() - - val signature = target.jvmMethod + val signature = override.jvmMethod if (targetMethod != signature && signature !in blacklist) { val bridge = generated.getOrPut(signature) { - Bridge(target, signature) + Bridge(override, signature) } - bridge.overriddenSymbols += target.symbol + bridge.overriddenSymbols += override.symbol } } @@ -362,16 +360,6 @@ 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/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmValueClassAbstractLowering.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmValueClassAbstractLowering.kt index 09abc4cde62..9a0453c82ed 100644 --- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmValueClassAbstractLowering.kt +++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmValueClassAbstractLowering.kt @@ -81,6 +81,16 @@ internal abstract class JvmValueClassAbstractLowering(val context: JvmBackendCon val replacement = replacements.getReplacementFunction(function) if (replacement == null) { function.transformChildrenVoid() + // Non-mangled functions can override mangled functions under some conditions, e.g., a function + // `fun f(): Nothing` can override a function `fun f(): UInt`. The former is not mangled, while + // the latter is. + // + // This is a potential problem for bridge generation, where we have to ensure that the overridden + // symbols are always up to date. Right now they might not be since we lower each file independently + // and since deserialized declarations are not mangled at all. + if (function is IrSimpleFunction) { + function.overriddenSymbols = replacements.replaceOverriddenSymbols(function) + } return null } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedInlineClassReplacements.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedInlineClassReplacements.kt index 94b6b6525d4..a9a8ba07508 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedInlineClassReplacements.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedInlineClassReplacements.kt @@ -19,6 +19,7 @@ import org.jetbrains.kotlin.ir.builders.declarations.buildFun import org.jetbrains.kotlin.ir.builders.declarations.buildProperty import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl import org.jetbrains.kotlin.ir.types.impl.IrStarProjectionImpl import org.jetbrains.kotlin.ir.types.isInt @@ -304,11 +305,21 @@ class MemoizedInlineClassReplacements( } } - overriddenSymbols = function.overriddenSymbols.map { - getReplacementFunction(it.owner)?.symbol ?: it - } + overriddenSymbols = replaceOverriddenSymbols(function) } body() } + + override val replaceOverriddenSymbols: (IrSimpleFunction) -> List = + storageManager.createMemoizedFunction { irSimpleFunction -> + irSimpleFunction.overriddenSymbols.map { + computeOverrideReplacement(it.owner).symbol + } + } + + private fun computeOverrideReplacement(function: IrSimpleFunction): IrSimpleFunction = + getReplacementFunction(function) ?: function.also { + function.overriddenSymbols = replaceOverriddenSymbols(function) + } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedMultiFieldValueClassReplacements.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedMultiFieldValueClassReplacements.kt index 34d71dfae8c..bac2f39420b 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedMultiFieldValueClassReplacements.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedMultiFieldValueClassReplacements.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.backend.jvm import org.jetbrains.kotlin.ir.declarations.IrFactory import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.storage.LockBasedStorageManager import java.util.concurrent.ConcurrentHashMap @@ -29,4 +30,8 @@ class MemoizedMultiFieldValueClassReplacements( override val getReplacementFunction: (IrFunction) -> IrSimpleFunction? = storageManager.createMemoizedFunctionWithNullableValues { TODO() } + + override val replaceOverriddenSymbols: (IrSimpleFunction) -> List = storageManager.createMemoizedFunction { + TODO() + } } diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedValueClassAbstractReplacements.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedValueClassAbstractReplacements.kt index a1dba80c3c1..e94c6cd2088 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedValueClassAbstractReplacements.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MemoizedValueClassAbstractReplacements.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.backend.jvm import org.jetbrains.kotlin.ir.declarations.IrFactory import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol abstract class MemoizedValueClassAbstractReplacements(protected val irFactory: IrFactory, protected val context: JvmBackendContext) { /** @@ -17,4 +18,5 @@ abstract class MemoizedValueClassAbstractReplacements(protected val irFactory: I abstract val originalFunctionForStaticReplacement: MutableMap + abstract val replaceOverriddenSymbols: (IrSimpleFunction) -> List } \ No newline at end of file diff --git a/compiler/testData/codegen/box/inlineClasses/kt52394.kt b/compiler/testData/codegen/box/inlineClasses/kt52394.kt new file mode 100644 index 00000000000..a7f825654c9 --- /dev/null +++ b/compiler/testData/codegen/box/inlineClasses/kt52394.kt @@ -0,0 +1,30 @@ +// WITH_REFLECT +// TARGET_BACKEND: JVM +import kotlin.reflect.full.declaredFunctions + +annotation class Anno(val value: String) + +@JvmInline +value class A(val value: String) + +abstract class B { + @Anno(value = "K") + abstract fun f(): A? +} + +class C : B() { + override fun f(): A? = A("O") +} + +class D : B() { + override fun f(): Nothing? = null +} + +fun box(): String { + val o = if ((D() as B).f() == null) (C() as B).f()!!.value else "Fail" + + val annotations = B::class.declaredFunctions.single().annotations + val k = (annotations.single() as Anno).value + + return o + k +} 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 da21eed07c0..4e9474e8981 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 @@ -21001,6 +21001,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/inlineClasses/kt51672.kt"); } + @Test + @TestMetadata("kt52394.kt") + public void testKt52394() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/kt52394.kt"); + } + @Test @TestMetadata("mangledDefaultParameterFunction.kt") public void testMangledDefaultParameterFunction() 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 ed0985ff3bf..157940fa69c 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 @@ -21475,6 +21475,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/inlineClasses/kt51672.kt"); } + @Test + @TestMetadata("kt52394.kt") + public void testKt52394() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/kt52394.kt"); + } + @Test @TestMetadata("mangledDefaultParameterFunction.kt") public void testMangledDefaultParameterFunction() 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 3248bc9567f..42f1b051dc9 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -17534,6 +17534,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/inlineClasses/kt51672.kt"); } + @TestMetadata("kt52394.kt") + public void testKt52394() throws Exception { + runTest("compiler/testData/codegen/box/inlineClasses/kt52394.kt"); + } + @TestMetadata("mangledDefaultParameterFunction.kt") public void testMangledDefaultParameterFunction() throws Exception { runTest("compiler/testData/codegen/box/inlineClasses/mangledDefaultParameterFunction.kt", TransformersFunctions.getReplaceOptionalJvmInlineAnnotationWithReal());