JVM IR: Mangle overridden symbols in non-inline functions (KT-52394)
This commit is contained in:
+6
@@ -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 {
|
||||
|
||||
+3
-15
@@ -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
|
||||
|
||||
|
||||
+10
@@ -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
|
||||
}
|
||||
|
||||
|
||||
+14
-3
@@ -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<IrSimpleFunctionSymbol> =
|
||||
storageManager.createMemoizedFunction { irSimpleFunction ->
|
||||
irSimpleFunction.overriddenSymbols.map {
|
||||
computeOverrideReplacement(it.owner).symbol
|
||||
}
|
||||
}
|
||||
|
||||
private fun computeOverrideReplacement(function: IrSimpleFunction): IrSimpleFunction =
|
||||
getReplacementFunction(function) ?: function.also {
|
||||
function.overriddenSymbols = replaceOverriddenSymbols(function)
|
||||
}
|
||||
}
|
||||
|
||||
+5
@@ -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<IrSimpleFunctionSymbol> = storageManager.createMemoizedFunction {
|
||||
TODO()
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -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<IrFunction, IrFunction>
|
||||
|
||||
abstract val replaceOverriddenSymbols: (IrSimpleFunction) -> List<IrSimpleFunctionSymbol>
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
+6
@@ -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 {
|
||||
|
||||
+6
@@ -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 {
|
||||
|
||||
+5
@@ -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());
|
||||
|
||||
Reference in New Issue
Block a user