Revert "JVM IR: remove obsolete isDefaultImplsBridge in findInterfaceImplementation"

This reverts commit d41d1bf64d.
This commit is contained in:
Alexander Udalov
2020-12-08 17:44:43 +01:00
parent 69c88a8a0a
commit 3370fa03d7
2 changed files with 29 additions and 15 deletions
@@ -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.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.* import org.jetbrains.kotlin.backend.jvm.ir.*
import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.builtins.StandardNames
@@ -263,14 +264,14 @@ internal fun IrSimpleFunction.findInterfaceImplementation(jvmDefaultMode: JvmDef
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 { if (overriddenSymbols.any {
!it.owner.parentAsClass.isInterface && !it.owner.parentAsClass.isInterface &&
it.owner.modality != Modality.ABSTRACT && it.owner.modality != Modality.ABSTRACT &&
it.owner.resolveFakeOverride() == implementation it.owner.resolveFakeOverride(toSkip = ::isDefaultImplsBridge) == implementation
}) { }) {
return null return null
} }
@@ -285,3 +286,6 @@ internal fun IrSimpleFunction.findInterfaceImplementation(jvmDefaultMode: JvmDef
return implementation return implementation
} }
private fun isDefaultImplsBridge(f: IrSimpleFunction) =
f.origin == JvmLoweredDeclarationOrigin.SUPER_INTERFACE_METHOD_BRIDGE
@@ -24,26 +24,36 @@ val IrSimpleFunction.target: IrSimpleFunction
else else
resolveFakeOverride() ?: error("Could not resolveFakeOverride() for ${this.render()}") resolveFakeOverride() ?: error("Could not resolveFakeOverride() for ${this.render()}")
val IrFunction.target: IrFunction val IrFunction.target: IrFunction get() = when (this) {
get() = when (this) { is IrSimpleFunction -> this.target
is IrSimpleFunction -> this.target is IrConstructor -> this
is IrConstructor -> this else -> error(this)
else -> error(this) }
}
fun IrSimpleFunction.collectRealOverrides(filter: (IrOverridableMember) -> Boolean = { false }): Set<IrSimpleFunction> { fun IrSimpleFunction.collectRealOverrides(
if (isReal) return setOf(this) toSkip: (IrSimpleFunction) -> Boolean = { false },
filter: (IrOverridableMember) -> Boolean = { false }
): Set<IrSimpleFunction> {
if (isReal && !toSkip(this)) return setOf(this)
return this.overriddenSymbols return this.overriddenSymbols
.map { it.owner } .map { it.owner }
.collectAndFilterRealOverrides(filter) .collectAndFilterRealOverrides(
{
require(it is IrSimpleFunction) { "Expected IrSimpleFunction: ${it.render()}" }
toSkip(it)
},
filter
)
.map { it as IrSimpleFunction } .map { it as IrSimpleFunction }
.toSet() .toSet()
} }
fun Collection<IrOverridableMember>.collectAndFilterRealOverrides( fun Collection<IrOverridableMember>.collectAndFilterRealOverrides(
toSkip: (IrOverridableMember) -> Boolean = { false },
filter: (IrOverridableMember) -> Boolean = { false } filter: (IrOverridableMember) -> Boolean = { false }
): Set<IrOverridableMember> { ): Set<IrOverridableMember> {
val visited = mutableSetOf<IrOverridableMember>() val visited = mutableSetOf<IrOverridableMember>()
val realOverrides = mutableSetOf<IrOverridableMember>() val realOverrides = mutableSetOf<IrOverridableMember>()
@@ -58,7 +68,7 @@ fun Collection<IrOverridableMember>.collectAndFilterRealOverrides(
fun collectRealOverrides(member: IrOverridableMember) { fun collectRealOverrides(member: IrOverridableMember) {
if (!visited.add(member) || filter(member)) return if (!visited.add(member) || filter(member)) return
if (member.isReal) { if (member.isReal && !toSkip(member)) {
realOverrides += member realOverrides += member
} else { } else {
overriddenSymbols(member).forEach { collectRealOverrides(it.owner as IrOverridableMember) } overriddenSymbols(member).forEach { collectRealOverrides(it.owner as IrOverridableMember) }
@@ -83,13 +93,13 @@ fun Collection<IrOverridableMember>.collectAndFilterRealOverrides(
} }
// TODO: use this implementation instead of any other // 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) { return if (allowAbstract) {
val reals = collectRealOverrides() val reals = collectRealOverrides(toSkip)
if (reals.isEmpty()) error("No real overrides for ${this.render()}") if (reals.isEmpty()) error("No real overrides for ${this.render()}")
reals.first() reals.first()
} else { } else {
collectRealOverrides { it.modality == Modality.ABSTRACT } collectRealOverrides(toSkip, { it.modality == Modality.ABSTRACT })
.let { realOverrides -> .let { realOverrides ->
// Kotlin forbids conflicts between overrides, but they may trickle down from Java. // Kotlin forbids conflicts between overrides, but they may trickle down from Java.
realOverrides.singleOrNull { it.parent.safeAs<IrClass>()?.isInterface != true } realOverrides.singleOrNull { it.parent.safeAs<IrClass>()?.isInterface != true }