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.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
@@ -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<IrSimpleFunction> {
if (isReal) return setOf(this)
fun IrSimpleFunction.collectRealOverrides(
toSkip: (IrSimpleFunction) -> Boolean = { false },
filter: (IrOverridableMember) -> Boolean = { false }
): Set<IrSimpleFunction> {
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<IrOverridableMember>.collectAndFilterRealOverrides(
toSkip: (IrOverridableMember) -> Boolean = { false },
filter: (IrOverridableMember) -> Boolean = { false }
): Set<IrOverridableMember> {
val visited = mutableSetOf<IrOverridableMember>()
val realOverrides = mutableSetOf<IrOverridableMember>()
@@ -58,7 +68,7 @@ fun Collection<IrOverridableMember>.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<IrOverridableMember>.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<IrClass>()?.isInterface != true }