JVM IR: do not generate certain special bridges as final
Special bridges which are generated as a replacement for a non-final fake override and use invokespecial to call the already existing implementation in the superclass, should not be final. Otherwise we can't generate an override for the original Kotlin function in a subclass with the same JVM signature.
This commit is contained in:
+5
-7
@@ -136,7 +136,8 @@ private class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass,
|
||||
val signature: Method,
|
||||
val specializedReturnType: IrType? = null,
|
||||
val methodInfo: SpecialMethodWithDefaultInfo? = null,
|
||||
val superQualifierSymbol: IrClassSymbol? = null
|
||||
val superQualifierSymbol: IrClassSymbol? = null,
|
||||
val isFinal: Boolean = true,
|
||||
)
|
||||
|
||||
override fun lower(irFile: IrFile) = irFile.transformChildrenVoid()
|
||||
@@ -229,7 +230,8 @@ private class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass,
|
||||
val superTarget = irFunction.overriddenSymbols.first { !it.owner.parentAsClass.isInterface }.owner
|
||||
val superBridge = SpecialBridge(
|
||||
irFunction, irFunction.jvmMethod, superQualifierSymbol = superTarget.parentAsClass.symbol,
|
||||
methodInfo = specialBridge.methodInfo?.copy(argumentsToCheck = 0) // For potential argument boxing
|
||||
methodInfo = specialBridge.methodInfo?.copy(argumentsToCheck = 0), // For potential argument boxing
|
||||
isFinal = false,
|
||||
)
|
||||
irClass.declarations.remove(irFunction)
|
||||
irClass.addSpecialBridge(superBridge, superTarget)
|
||||
@@ -366,8 +368,7 @@ private class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass,
|
||||
|
||||
private fun IrClass.addSpecialBridge(specialBridge: SpecialBridge, target: IrSimpleFunction): IrSimpleFunction =
|
||||
addFunction {
|
||||
// FIXME: This seems to be a work-around for superfluous specialized collection stubs
|
||||
modality = if (!target.isCollectionStub()) Modality.FINAL else Modality.OPEN
|
||||
modality = if (specialBridge.isFinal) Modality.FINAL else Modality.OPEN
|
||||
origin = IrDeclarationOrigin.BRIDGE_SPECIAL
|
||||
name = Name.identifier(specialBridge.signature.name)
|
||||
returnType = specialBridge.specializedReturnType ?: specialBridge.overridden.returnType.eraseTypeParameters()
|
||||
@@ -490,7 +491,4 @@ private class BridgeLowering(val context: JvmBackendContext) : FileLoweringPass,
|
||||
get() = context.methodSignatureMapper.mapAsmMethod(this)
|
||||
}
|
||||
|
||||
private fun IrSimpleFunction.isCollectionStub(): Boolean =
|
||||
origin == IrDeclarationOrigin.IR_BUILTINS_STUB
|
||||
|
||||
private fun IrDeclaration.comesFromJava() = parentAsClass.origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
|
||||
import java.util.AbstractMap
|
||||
|
||||
// Neither of getSize, getKeys, getEntries, getValues generated here should be final.
|
||||
abstract class AbstractMutableMap<K, V> : MutableMap<K, V>, AbstractMap<K, V>()
|
||||
|
||||
class MyMap<K, V> : AbstractMutableMap<K, V>() {
|
||||
override val size: Int
|
||||
get() = 1
|
||||
override val entries: MutableSet<MutableMap.MutableEntry<K, V>>
|
||||
get() = null!!
|
||||
}
|
||||
|
||||
fun box(): String =
|
||||
if (MyMap<String, String>().size == 1) "OK" else "Fail"
|
||||
+5
@@ -27216,6 +27216,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/specialBuiltins/removeSetInt.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("specialBridgeModality.kt")
|
||||
public void testSpecialBridgeModality() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/specialBuiltins/specialBridgeModality.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("throwable.kt")
|
||||
public void testThrowable() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/specialBuiltins/throwable.kt");
|
||||
|
||||
+5
@@ -26033,6 +26033,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/specialBuiltins/removeSetInt.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("specialBridgeModality.kt")
|
||||
public void testSpecialBridgeModality() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/specialBuiltins/specialBridgeModality.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("throwable.kt")
|
||||
public void testThrowable() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/specialBuiltins/throwable.kt");
|
||||
|
||||
+5
@@ -25720,6 +25720,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/specialBuiltins/removeSetInt.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("specialBridgeModality.kt")
|
||||
public void testSpecialBridgeModality() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/specialBuiltins/specialBridgeModality.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("throwable.kt")
|
||||
public void testThrowable() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/specialBuiltins/throwable.kt");
|
||||
|
||||
+5
@@ -25720,6 +25720,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/specialBuiltins/removeSetInt.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("specialBridgeModality.kt")
|
||||
public void testSpecialBridgeModality() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/specialBuiltins/specialBridgeModality.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("throwable.kt")
|
||||
public void testThrowable() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/specialBuiltins/throwable.kt");
|
||||
|
||||
Reference in New Issue
Block a user