JVM_IR: in InheritedDefaultMethodsOnClassesLowering, skip bridges when resolving overrides

This commit is contained in:
Georgy Bronnikov
2020-02-11 17:57:06 +03:00
parent 829e5908d0
commit c71e87068a
9 changed files with 65 additions and 7 deletions
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.backend.common.ir.passTypeArgumentsFrom
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
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.codegen.isJvmInterface
import org.jetbrains.kotlin.backend.jvm.ir.createDelegatingCallWithPlaceholderTypeArguments
import org.jetbrains.kotlin.backend.jvm.ir.createPlaceholderAnyNType
@@ -219,15 +220,23 @@ private class InterfaceObjectCallsLowering(val context: JvmBackendContext) : IrE
* interface implementation should be generated into the class containing the fake override; or null if the given function is not a fake
* override of any interface implementation or such method was already generated into the superclass or is a method from Any.
*/
private fun isDefaultImplsBridge(f: IrSimpleFunction) =
f.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE ||
f.origin == JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_TO_SYNTHETIC
internal fun IrSimpleFunction.findInterfaceImplementation(): IrSimpleFunction? {
if (!isFakeOverride) return null
parent.let { if (it is IrClass && it.isJvmInterface) return null }
val implementation = resolveFakeOverride() ?: return null
val implementation = resolveFakeOverride(toSkip = ::isDefaultImplsBridge) ?: return null
// Only generate interface delegation for functions immediately inherited from an interface.
// (Otherwise, delegation will be present in the parent class)
if (overriddenSymbols.any { !it.owner.parentAsClass.isInterface && it.owner.modality != Modality.ABSTRACT && it.owner.resolveFakeOverride() == implementation }) {
if (overriddenSymbols.any {
!it.owner.parentAsClass.isInterface &&
it.owner.modality != Modality.ABSTRACT &&
it.owner.resolveFakeOverride(toSkip = ::isDefaultImplsBridge) == implementation
}) {
return null
}
@@ -260,8 +260,8 @@ fun IrClass.isSubclassOf(ancestor: IrClass): Boolean {
return this.hasAncestorInSuperTypes()
}
fun IrSimpleFunction.collectRealOverrides(): Set<IrSimpleFunction> {
if (isReal) return setOf(this)
fun IrSimpleFunction.collectRealOverrides(toSkip: (IrSimpleFunction) -> Boolean = { false }): Set<IrSimpleFunction> {
if (isReal && !toSkip(this)) return setOf(this)
val visited = mutableSetOf<IrSimpleFunction>()
val realOverrides = mutableSetOf<IrSimpleFunction>()
@@ -269,7 +269,7 @@ fun IrSimpleFunction.collectRealOverrides(): Set<IrSimpleFunction> {
fun collectRealOverrides(func: IrSimpleFunction) {
if (!visited.add(func)) return
if (func.isReal) {
if (func.isReal && !toSkip(func)) {
realOverrides += func
} else {
func.overriddenSymbols.forEach { collectRealOverrides(it.owner) }
@@ -295,8 +295,8 @@ fun IrSimpleFunction.collectRealOverrides(): Set<IrSimpleFunction> {
// This implementation is from kotlin-native
// TODO: use this implementation instead of any other
fun IrSimpleFunction.resolveFakeOverride(): IrSimpleFunction? {
return collectRealOverrides().singleOrNull { it.modality != Modality.ABSTRACT }
fun IrSimpleFunction.resolveFakeOverride(toSkip: (IrSimpleFunction) -> Boolean = { false }): IrSimpleFunction? {
return collectRealOverrides(toSkip).singleOrNull { it.modality != Modality.ABSTRACT }
}
fun IrSimpleFunction.isOrOverridesSynthesized(): Boolean {
+19
View File
@@ -0,0 +1,19 @@
// IGNORE_BACKEND_FIR: JVM_IR
interface A {
val result: String get() = "Fail"
}
interface B : A
abstract class AImpl : A
abstract class BImpl : AImpl(), B
interface C : B {
override val result: String get() = "OK"
}
object CImpl : BImpl(), C
fun box(): String = CImpl.result
@@ -28052,6 +28052,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/traits/diamondPropertyAccessors.kt");
}
@TestMetadata("doubleDiamond.kt")
public void testDoubleDiamond() throws Exception {
runTest("compiler/testData/codegen/box/traits/doubleDiamond.kt");
}
@TestMetadata("genericMethod.kt")
public void testGenericMethod() throws Exception {
runTest("compiler/testData/codegen/box/traits/genericMethod.kt");
@@ -26869,6 +26869,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/traits/diamondPropertyAccessors.kt");
}
@TestMetadata("doubleDiamond.kt")
public void testDoubleDiamond() throws Exception {
runTest("compiler/testData/codegen/box/traits/doubleDiamond.kt");
}
@TestMetadata("genericMethod.kt")
public void testGenericMethod() throws Exception {
runTest("compiler/testData/codegen/box/traits/genericMethod.kt");
@@ -26556,6 +26556,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/traits/diamondPropertyAccessors.kt");
}
@TestMetadata("doubleDiamond.kt")
public void testDoubleDiamond() throws Exception {
runTest("compiler/testData/codegen/box/traits/doubleDiamond.kt");
}
@TestMetadata("genericMethod.kt")
public void testGenericMethod() throws Exception {
runTest("compiler/testData/codegen/box/traits/genericMethod.kt");
@@ -26556,6 +26556,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/traits/diamondPropertyAccessors.kt");
}
@TestMetadata("doubleDiamond.kt")
public void testDoubleDiamond() throws Exception {
runTest("compiler/testData/codegen/box/traits/doubleDiamond.kt");
}
@TestMetadata("genericMethod.kt")
public void testGenericMethod() throws Exception {
runTest("compiler/testData/codegen/box/traits/genericMethod.kt");
@@ -21567,6 +21567,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/traits/diamondPropertyAccessors.kt");
}
@TestMetadata("doubleDiamond.kt")
public void testDoubleDiamond() throws Exception {
runTest("compiler/testData/codegen/box/traits/doubleDiamond.kt");
}
@TestMetadata("genericMethod.kt")
public void testGenericMethod() throws Exception {
runTest("compiler/testData/codegen/box/traits/genericMethod.kt");
@@ -21627,6 +21627,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/traits/diamondPropertyAccessors.kt");
}
@TestMetadata("doubleDiamond.kt")
public void testDoubleDiamond() throws Exception {
runTest("compiler/testData/codegen/box/traits/doubleDiamond.kt");
}
@TestMetadata("genericMethod.kt")
public void testGenericMethod() throws Exception {
runTest("compiler/testData/codegen/box/traits/genericMethod.kt");