diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InheritedDefaultMethodsOnClassesLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InheritedDefaultMethodsOnClassesLowering.kt index ecf892ef780..4c286cafaee 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InheritedDefaultMethodsOnClassesLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/InheritedDefaultMethodsOnClassesLowering.kt @@ -14,6 +14,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.* import org.jetbrains.kotlin.builtins.StandardNames @@ -263,14 +264,14 @@ internal fun IrSimpleFunction.findInterfaceImplementation(jvmDefaultMode: JvmDef 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 + it.owner.resolveFakeOverride(toSkip = ::isDefaultImplsBridge) == implementation }) { return null } @@ -285,3 +286,6 @@ internal fun IrSimpleFunction.findInterfaceImplementation(jvmDefaultMode: JvmDef return implementation } + +private fun isDefaultImplsBridge(f: IrSimpleFunction) = + f.origin == JvmLoweredDeclarationOrigin.SUPER_INTERFACE_METHOD_BRIDGE diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrFakeOverrideUtils.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrFakeOverrideUtils.kt index 20c456a4c2a..5639181114c 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrFakeOverrideUtils.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrFakeOverrideUtils.kt @@ -24,26 +24,36 @@ val IrSimpleFunction.target: IrSimpleFunction else resolveFakeOverride() ?: error("Could not resolveFakeOverride() for ${this.render()}") -val IrFunction.target: IrFunction - get() = when (this) { - is IrSimpleFunction -> this.target - is IrConstructor -> this - else -> error(this) - } +val IrFunction.target: IrFunction get() = when (this) { + is IrSimpleFunction -> this.target + is IrConstructor -> this + else -> error(this) +} -fun IrSimpleFunction.collectRealOverrides(filter: (IrOverridableMember) -> Boolean = { false }): Set { - if (isReal) return setOf(this) +fun IrSimpleFunction.collectRealOverrides( + toSkip: (IrSimpleFunction) -> Boolean = { false }, + filter: (IrOverridableMember) -> Boolean = { false } +): Set { + if (isReal && !toSkip(this)) return setOf(this) return this.overriddenSymbols .map { it.owner } - .collectAndFilterRealOverrides(filter) + .collectAndFilterRealOverrides( + { + require(it is IrSimpleFunction) { "Expected IrSimpleFunction: ${it.render()}" } + toSkip(it) + }, + filter + ) .map { it as IrSimpleFunction } .toSet() } fun Collection.collectAndFilterRealOverrides( + toSkip: (IrOverridableMember) -> Boolean = { false }, filter: (IrOverridableMember) -> Boolean = { false } ): Set { + val visited = mutableSetOf() val realOverrides = mutableSetOf() @@ -58,7 +68,7 @@ fun Collection.collectAndFilterRealOverrides( fun collectRealOverrides(member: IrOverridableMember) { if (!visited.add(member) || filter(member)) return - if (member.isReal) { + if (member.isReal && !toSkip(member)) { realOverrides += member } else { overriddenSymbols(member).forEach { collectRealOverrides(it.owner as IrOverridableMember) } @@ -83,13 +93,13 @@ fun Collection.collectAndFilterRealOverrides( } // TODO: use this implementation instead of any other -fun IrSimpleFunction.resolveFakeOverride(allowAbstract: Boolean = false): IrSimpleFunction? { +fun IrSimpleFunction.resolveFakeOverride(allowAbstract: Boolean = false, toSkip: (IrSimpleFunction) -> Boolean = { false }): IrSimpleFunction? { return if (allowAbstract) { - val reals = collectRealOverrides() + val reals = collectRealOverrides(toSkip) if (reals.isEmpty()) error("No real overrides for ${this.render()}") reals.first() } else { - collectRealOverrides { it.modality == Modality.ABSTRACT } + collectRealOverrides(toSkip, { it.modality == Modality.ABSTRACT }) .let { realOverrides -> // Kotlin forbids conflicts between overrides, but they may trickle down from Java. realOverrides.singleOrNull { it.parent.safeAs()?.isInterface != true }