IR: properly compute IrProperty.resolveFakeOverride()

Now that IrProperty has its own overriddenSymbols, we can generalize the
search for fake overrides. Also works for fake override properties
derived from Java fields.
This commit is contained in:
Georgy Bronnikov
2021-05-20 21:05:08 +03:00
parent 3769fd8e07
commit fca804de14
9 changed files with 60 additions and 88 deletions
@@ -776,8 +776,8 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
return this.overriddenSymbols return this.overriddenSymbols
.map { it.owner } .map { it.owner }
.collectAndFilterRealOverrides(getOverriddenPropertySymbols = IrProperty::overriddenSymbols) .collectAndFilterRealOverrides()
.firstOrNull() as? IrProperty .firstOrNull()
?: throw AssertionError("No real override for ${this.render()}") ?: throw AssertionError("No real override for ${this.render()}")
} }
@@ -48,7 +48,9 @@ interface IrDeclaration : IrStatement, IrSymbolOwner, IrMutableAnnotationContain
abstract class IrDeclarationBase : IrElementBase(), IrDeclaration abstract class IrDeclarationBase : IrElementBase(), IrDeclaration
interface IrOverridableDeclaration<S : IrSymbol> : IrDeclaration { interface IrOverridableDeclaration<S : IrSymbol> : IrOverridableMember {
override val symbol: S
val isFakeOverride: Boolean
var overriddenSymbols: List<S> var overriddenSymbols: List<S>
} }
@@ -25,7 +25,6 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
abstract class IrProperty : abstract class IrProperty :
IrDeclarationBase(), IrDeclarationBase(),
IrPossiblyExternalDeclaration, IrPossiblyExternalDeclaration,
IrOverridableMember,
IrOverridableDeclaration<IrPropertySymbol>, IrOverridableDeclaration<IrPropertySymbol>,
IrMetadataSourceOwner, IrMetadataSourceOwner,
IrAttributeContainer, IrAttributeContainer,
@@ -40,7 +39,7 @@ abstract class IrProperty :
abstract val isLateinit: Boolean abstract val isLateinit: Boolean
abstract val isDelegated: Boolean abstract val isDelegated: Boolean
abstract val isExpect: Boolean abstract val isExpect: Boolean
abstract val isFakeOverride: Boolean abstract override val isFakeOverride: Boolean
abstract var backingField: IrField? abstract var backingField: IrField?
abstract var getter: IrSimpleFunction? abstract var getter: IrSimpleFunction?
@@ -12,14 +12,13 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
abstract class IrSimpleFunction : abstract class IrSimpleFunction :
IrFunction(), IrFunction(),
IrOverridableDeclaration<IrSimpleFunctionSymbol>, IrOverridableDeclaration<IrSimpleFunctionSymbol>,
IrOverridableMember,
IrAttributeContainer { IrAttributeContainer {
abstract override val symbol: IrSimpleFunctionSymbol abstract override val symbol: IrSimpleFunctionSymbol
abstract val isTailrec: Boolean abstract val isTailrec: Boolean
abstract val isSuspend: Boolean abstract val isSuspend: Boolean
abstract val isFakeOverride: Boolean abstract override val isFakeOverride: Boolean
abstract val isOperator: Boolean abstract val isOperator: Boolean
abstract val isInfix: Boolean abstract val isInfix: Boolean
@@ -74,7 +74,7 @@ class IrLazyProperty(
override var overriddenSymbols: List<IrPropertySymbol> by lazyVar(stubGenerator.lock) { override var overriddenSymbols: List<IrPropertySymbol> by lazyVar(stubGenerator.lock) {
descriptor.overriddenDescriptors.mapTo(ArrayList()) { descriptor.overriddenDescriptors.mapTo(ArrayList()) {
stubGenerator.generatePropertyStub(it).symbol stubGenerator.generatePropertyStub(it.original).symbol
} }
} }
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.collectAndFilterRealOverrides
import org.jetbrains.kotlin.ir.util.isReal import org.jetbrains.kotlin.ir.util.isReal
import org.jetbrains.kotlin.ir.util.render import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo
@@ -36,9 +35,6 @@ abstract class FakeOverrideBuilderStrategy {
protected abstract fun linkFunctionFakeOverride(declaration: IrFakeOverrideFunction) protected abstract fun linkFunctionFakeOverride(declaration: IrFakeOverrideFunction)
protected abstract fun linkPropertyFakeOverride(declaration: IrFakeOverrideProperty) protected abstract fun linkPropertyFakeOverride(declaration: IrFakeOverrideProperty)
// TODO: need to make IrProperty carry overriddenSymbols.
val propertyOverriddenSymbols: MutableMap<IrOverridableMember, List<IrSymbol>> = mutableMapOf()
} }
fun buildFakeOverrideMember(superType: IrType, member: IrOverridableMember, clazz: IrClass): IrOverridableMember { fun buildFakeOverrideMember(superType: IrType, member: IrOverridableMember, clazz: IrClass): IrOverridableMember {
@@ -89,35 +85,32 @@ class IrOverridingUtil(
originalSuperTypes.clear() originalSuperTypes.clear()
} }
private var IrOverridableMember.overriddenSymbols: List<IrSymbol> private val IrOverridableMember.overriddenSymbols: List<IrSymbol>
get() = when (this) { get() = (this as? IrOverridableDeclaration<*>)?.overriddenSymbols
is IrSimpleFunction -> this.overriddenSymbols ?: error("Unexpected IrOverridableMember: $this")
is IrProperty -> fakeOverrideBuilder.propertyOverriddenSymbols[this]
?: error("No overridden symbols for ${this.render()}") private fun IrOverridableMember.setOverriddenSymbols(value: List<IrSymbol>) {
when (this) {
is IrSimpleFunction -> this.overriddenSymbols =
value.map { it as? IrSimpleFunctionSymbol ?: error("Unexpected function overridden symbol: $it") }
is IrProperty -> {
this.overriddenSymbols =
value.map { it as? IrPropertySymbol ?: error("Unexpected property overridden symbol: $it") }
val getter = this.getter ?: error("Property has no getter: ${render()}")
getter.overriddenSymbols = value.map { (it.owner as IrProperty).getter!!.symbol }
this.setter?.let { setter ->
setter.overriddenSymbols = value.mapNotNull { (it.owner as IrProperty).setter?.symbol }
}
}
else -> error("Unexpected declaration for overriddenSymbols: $this") else -> error("Unexpected declaration for overriddenSymbols: $this")
} }
set(value) { }
when (this) {
is IrSimpleFunction -> this.overriddenSymbols =
value.map { it as? IrSimpleFunctionSymbol ?: error("Unexpected function overridden symbol: $it") }
is IrProperty -> {
fakeOverrideBuilder.propertyOverriddenSymbols[this] =
value.map { it as? IrPropertySymbol ?: error("Unexpected property overridden symbol: $it") }
val getter = this.getter ?: error("Property has no getter: ${render()}")
getter.overriddenSymbols = value.map { (it.owner as IrProperty).getter!!.symbol }
this.setter?.let { setter ->
setter.overriddenSymbols = value.mapNotNull { (it.owner as IrProperty).setter?.symbol }
}
}
else -> error("Unexpected declaration for overriddenSymbols: $this")
}
}
fun buildFakeOverridesForClass(clazz: IrClass) { fun buildFakeOverridesForClass(clazz: IrClass) {
val superTypes = clazz.superTypes val superTypes = clazz.superTypes
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
val fromCurrent = clazz.declarations.filter { it is IrOverridableMember } as List<IrOverridableMember> val fromCurrent = clazz.declarations.filterIsInstance<IrOverridableMember>()
val allFromSuper = superTypes.flatMap { superType -> val allFromSuper = superTypes.flatMap { superType ->
val superClass = superType.getClass() ?: error("Unexpected super type: $superType") val superClass = superType.getClass() ?: error("Unexpected super type: $superType")
@@ -147,19 +140,8 @@ class IrOverridingUtil(
clazz: IrClass, clazz: IrClass,
implementedMembers: List<IrOverridableMember> = emptyList() implementedMembers: List<IrOverridableMember> = emptyList()
): List<IrOverridableMember> { ): List<IrOverridableMember> {
fakeOverrideBuilder.propertyOverriddenSymbols.clear()
val overriddenMembers = (clazz.declarations.filterIsInstance<IrOverridableMember>() + implementedMembers) val overriddenMembers = (clazz.declarations.filterIsInstance<IrOverridableMember>() + implementedMembers)
.flatMap { .flatMap { member -> member.overriddenSymbols.map { it.owner } }
when (it) {
is IrSimpleFunction -> it.overriddenSymbols.map { it.owner }
// TODO: use IrProperty.overriddenSymbols instead: KT-47019
is IrProperty -> (it.getter ?: it.setter)?.overriddenSymbols
?.map { it.owner.correspondingPropertySymbol!!.owner }
?: emptyList()
else -> error("Unexpected IrOverridableMember: $it")
}
}
.toSet() .toSet()
val unoverriddenSuperMembers = clazz.superTypes.flatMap { superType -> val unoverriddenSuperMembers = clazz.superTypes.flatMap { superType ->
@@ -242,7 +224,7 @@ class IrOverridingUtil(
} }
} }
//strategy.setOverriddenDescriptors(fromCurrent, overridden) //strategy.setOverriddenDescriptors(fromCurrent, overridden)
fromCurrent.overriddenSymbols = overridden.map { it.original.symbol } fromCurrent.setOverriddenSymbols(overridden.map { it.original.symbol })
return bound return bound
} }
@@ -400,7 +382,7 @@ class IrOverridingUtil(
} }
} }
fakeOverride.overriddenSymbols = effectiveOverridden.map { it.original.symbol } fakeOverride.setOverriddenSymbols(effectiveOverridden.map { it.original.symbol })
assert( assert(
fakeOverride.overriddenSymbols.isNotEmpty() fakeOverride.overriddenSymbols.isNotEmpty()
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.ir.util
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
val IrDeclaration.isReal: Boolean get() = !isFakeOverride val IrDeclaration.isReal: Boolean get() = !isFakeOverride
@@ -31,65 +31,50 @@ val IrFunction.target: IrFunction get() = when (this) {
else -> error(this) else -> error(this)
} }
fun IrSimpleFunction.collectRealOverrides( fun <S : IrSymbol, T : IrOverridableDeclaration<S>> T.collectRealOverrides(
toSkip: (IrSimpleFunction) -> Boolean = { false }, toSkip: (T) -> Boolean = { false },
filter: (IrOverridableMember) -> Boolean = { false } filter: (T) -> Boolean = { false }
): Set<IrSimpleFunction> { ): Set<T> {
if (isReal && !toSkip(this)) return setOf(this) if (isReal && !toSkip(this)) return setOf(this)
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
return this.overriddenSymbols return this.overriddenSymbols
.map { it.owner } .map { it.owner as T }
.collectAndFilterRealOverrides( .collectAndFilterRealOverrides(toSkip, filter)
{
require(it is IrSimpleFunction) { "Expected IrSimpleFunction: ${it.render()}" }
toSkip(it)
},
filter
) as Set<IrSimpleFunction>
} }
fun Collection<IrOverridableMember>.collectAndFilterRealOverrides( fun <S : IrSymbol, T : IrOverridableDeclaration<S>> Collection<T>.collectAndFilterRealOverrides(
toSkip: (IrOverridableMember) -> Boolean = { false }, toSkip: (T) -> Boolean = { false },
filter: (IrOverridableMember) -> Boolean = { false }, filter: (T) -> Boolean = { false }
getOverriddenPropertySymbols: IrProperty.() -> List<IrPropertySymbol> = { ): Set<T> {
// TODO: use IrProperty.overriddenSymbols instead: KT-47019
// (at the moment it breaks K/N in at least :kotlin-native:backend.native:tests:coroutines_functionReference_eqeq_name)
(getter ?: setter)?.overriddenSymbols?.mapNotNull { it.owner.correspondingPropertySymbol }.orEmpty()
},
): Set<IrOverridableMember> {
val visited = mutableSetOf<IrOverridableMember>() val visited = mutableSetOf<T>()
val realOverrides = mutableMapOf<Any, IrOverridableMember>() val realOverrides = mutableMapOf<Any, T>()
/* /*
Due to IR copying in performByIrFile, overrides should only be distinguished up to their signatures. Due to IR copying in performByIrFile, overrides should only be distinguished up to their signatures.
*/ */
fun IrOverridableMember.toKey(): Any = symbol.signature ?: this fun T.toKey(): Any = symbol.signature ?: this
fun overriddenSymbols(declaration: IrOverridableMember) = when (declaration) { fun collectRealOverrides(member: T) {
is IrSimpleFunction -> declaration.overriddenSymbols
is IrProperty -> declaration.getOverriddenPropertySymbols()
else -> error("Unexpected overridable member: ${declaration.render()}")
}
fun collectRealOverrides(member: IrOverridableMember) {
if (!visited.add(member) || filter(member)) return if (!visited.add(member) || filter(member)) return
if (member.isReal && !toSkip(member)) { if (member.isReal && !toSkip(member)) {
realOverrides[member.toKey()] = member realOverrides[member.toKey()] = member
} else { } else {
overriddenSymbols(member).forEach { collectRealOverrides(it.owner as IrOverridableMember) } @Suppress("UNCHECKED_CAST")
member.overriddenSymbols.forEach { collectRealOverrides(it.owner as T) }
} }
} }
this.forEach { collectRealOverrides(it) } this.forEach { collectRealOverrides(it) }
fun excludeRepeated(member: IrOverridableMember) { fun excludeRepeated(member: T) {
if (!visited.add(member)) return if (!visited.add(member)) return
overriddenSymbols(member).forEach { member.overriddenSymbols.forEach {
val owner = it.owner as IrOverridableMember @Suppress("UNCHECKED_CAST")
val owner = it.owner as T
realOverrides.remove(owner.toKey()) realOverrides.remove(owner.toKey())
excludeRepeated(owner) excludeRepeated(owner)
} }
@@ -101,8 +86,16 @@ fun Collection<IrOverridableMember>.collectAndFilterRealOverrides(
return realOverrides.values.toSet() return realOverrides.values.toSet()
} }
fun Collection<IrOverridableMember>.collectAndFilterRealOverrides(): Set<IrOverridableMember> =
@Suppress("UNCHECKED_CAST")
(this as Collection<IrOverridableDeclaration<*>>).collectAndFilterRealOverrides()
// TODO: use this implementation instead of any other // TODO: use this implementation instead of any other
fun IrSimpleFunction.resolveFakeOverride(allowAbstract: Boolean = false, toSkip: (IrSimpleFunction) -> Boolean = { false }): IrSimpleFunction? { fun <S : IrSymbol, T : IrOverridableDeclaration<S>> T.resolveFakeOverride(
allowAbstract: Boolean = false,
toSkip: (T) -> Boolean = { false }
): T? {
if (!isFakeOverride) return this
return if (allowAbstract) { return if (allowAbstract) {
val reals = collectRealOverrides(toSkip) val reals = collectRealOverrides(toSkip)
if (reals.isEmpty()) error("No real overrides for ${this.render()}") if (reals.isEmpty()) error("No real overrides for ${this.render()}")
@@ -248,8 +248,6 @@ fun IrSimpleFunction.findInterfaceImplementation(): IrSimpleFunction? {
return resolveFakeOverride()?.run { if (parentAsClass.isInterface) this else null } return resolveFakeOverride()?.run { if (parentAsClass.isInterface) this else null }
} }
fun IrProperty.resolveFakeOverride(): IrProperty? = getter?.resolveFakeOverride()?.correspondingPropertySymbol?.owner
val IrClass.isAnnotationClass get() = kind == ClassKind.ANNOTATION_CLASS val IrClass.isAnnotationClass get() = kind == ClassKind.ANNOTATION_CLASS
val IrClass.isEnumClass get() = kind == ClassKind.ENUM_CLASS val IrClass.isEnumClass get() = kind == ClassKind.ENUM_CLASS
val IrClass.isEnumEntry get() = kind == ClassKind.ENUM_ENTRY val IrClass.isEnumEntry get() = kind == ClassKind.ENUM_ENTRY
@@ -159,7 +159,6 @@ class FakeOverrideBuilder(
private fun provideFakeOverrides(klass: IrClass) { private fun provideFakeOverrides(klass: IrClass) {
buildFakeOverrideChainsForClass(klass) buildFakeOverrideChainsForClass(klass)
propertyOverriddenSymbols.clear()
irOverridingUtil.clear() irOverridingUtil.clear()
haveFakeOverrides.add(klass) haveFakeOverrides.add(klass)
} }