JVM_IR: in InheritedDefaultMethodsOnClassesLowering, skip bridges when resolving overrides
This commit is contained in:
+11
-2
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
+5
@@ -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");
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
Generated
+5
@@ -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");
|
||||
|
||||
+5
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user