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:
Alexander Udalov
2020-02-11 20:22:26 +01:00
parent df046683cc
commit 3278451b07
6 changed files with 42 additions and 7 deletions
@@ -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"
@@ -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");
@@ -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");
@@ -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");
@@ -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");