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.lower.createIrBuilder
|
||||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
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.codegen.isJvmInterface
|
||||||
import org.jetbrains.kotlin.backend.jvm.ir.createDelegatingCallWithPlaceholderTypeArguments
|
import org.jetbrains.kotlin.backend.jvm.ir.createDelegatingCallWithPlaceholderTypeArguments
|
||||||
import org.jetbrains.kotlin.backend.jvm.ir.createPlaceholderAnyNType
|
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
|
* 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.
|
* 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? {
|
internal fun IrSimpleFunction.findInterfaceImplementation(): IrSimpleFunction? {
|
||||||
if (!isFakeOverride) return null
|
if (!isFakeOverride) return null
|
||||||
parent.let { if (it is IrClass && it.isJvmInterface) 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.
|
// Only generate interface delegation for functions immediately inherited from an interface.
|
||||||
// (Otherwise, delegation will be present in the parent class)
|
// (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
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -260,8 +260,8 @@ fun IrClass.isSubclassOf(ancestor: IrClass): Boolean {
|
|||||||
return this.hasAncestorInSuperTypes()
|
return this.hasAncestorInSuperTypes()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun IrSimpleFunction.collectRealOverrides(): Set<IrSimpleFunction> {
|
fun IrSimpleFunction.collectRealOverrides(toSkip: (IrSimpleFunction) -> Boolean = { false }): Set<IrSimpleFunction> {
|
||||||
if (isReal) return setOf(this)
|
if (isReal && !toSkip(this)) return setOf(this)
|
||||||
|
|
||||||
val visited = mutableSetOf<IrSimpleFunction>()
|
val visited = mutableSetOf<IrSimpleFunction>()
|
||||||
val realOverrides = mutableSetOf<IrSimpleFunction>()
|
val realOverrides = mutableSetOf<IrSimpleFunction>()
|
||||||
@@ -269,7 +269,7 @@ fun IrSimpleFunction.collectRealOverrides(): Set<IrSimpleFunction> {
|
|||||||
fun collectRealOverrides(func: IrSimpleFunction) {
|
fun collectRealOverrides(func: IrSimpleFunction) {
|
||||||
if (!visited.add(func)) return
|
if (!visited.add(func)) return
|
||||||
|
|
||||||
if (func.isReal) {
|
if (func.isReal && !toSkip(func)) {
|
||||||
realOverrides += func
|
realOverrides += func
|
||||||
} else {
|
} else {
|
||||||
func.overriddenSymbols.forEach { collectRealOverrides(it.owner) }
|
func.overriddenSymbols.forEach { collectRealOverrides(it.owner) }
|
||||||
@@ -295,8 +295,8 @@ fun IrSimpleFunction.collectRealOverrides(): Set<IrSimpleFunction> {
|
|||||||
|
|
||||||
// This implementation is from kotlin-native
|
// This implementation is from kotlin-native
|
||||||
// TODO: use this implementation instead of any other
|
// TODO: use this implementation instead of any other
|
||||||
fun IrSimpleFunction.resolveFakeOverride(): IrSimpleFunction? {
|
fun IrSimpleFunction.resolveFakeOverride(toSkip: (IrSimpleFunction) -> Boolean = { false }): IrSimpleFunction? {
|
||||||
return collectRealOverrides().singleOrNull { it.modality != Modality.ABSTRACT }
|
return collectRealOverrides(toSkip).singleOrNull { it.modality != Modality.ABSTRACT }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun IrSimpleFunction.isOrOverridesSynthesized(): Boolean {
|
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");
|
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")
|
@TestMetadata("genericMethod.kt")
|
||||||
public void testGenericMethod() throws Exception {
|
public void testGenericMethod() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/traits/genericMethod.kt");
|
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");
|
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")
|
@TestMetadata("genericMethod.kt")
|
||||||
public void testGenericMethod() throws Exception {
|
public void testGenericMethod() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/traits/genericMethod.kt");
|
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");
|
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")
|
@TestMetadata("genericMethod.kt")
|
||||||
public void testGenericMethod() throws Exception {
|
public void testGenericMethod() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/traits/genericMethod.kt");
|
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");
|
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")
|
@TestMetadata("genericMethod.kt")
|
||||||
public void testGenericMethod() throws Exception {
|
public void testGenericMethod() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/traits/genericMethod.kt");
|
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");
|
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")
|
@TestMetadata("genericMethod.kt")
|
||||||
public void testGenericMethod() throws Exception {
|
public void testGenericMethod() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/traits/genericMethod.kt");
|
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");
|
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")
|
@TestMetadata("genericMethod.kt")
|
||||||
public void testGenericMethod() throws Exception {
|
public void testGenericMethod() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/traits/genericMethod.kt");
|
runTest("compiler/testData/codegen/box/traits/genericMethod.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user