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
.map { it.owner }
.collectAndFilterRealOverrides(getOverriddenPropertySymbols = IrProperty::overriddenSymbols)
.firstOrNull() as? IrProperty
.collectAndFilterRealOverrides()
.firstOrNull()
?: throw AssertionError("No real override for ${this.render()}")
}
@@ -48,7 +48,9 @@ interface IrDeclaration : IrStatement, IrSymbolOwner, IrMutableAnnotationContain
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>
}
@@ -25,7 +25,6 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
abstract class IrProperty :
IrDeclarationBase(),
IrPossiblyExternalDeclaration,
IrOverridableMember,
IrOverridableDeclaration<IrPropertySymbol>,
IrMetadataSourceOwner,
IrAttributeContainer,
@@ -40,7 +39,7 @@ abstract class IrProperty :
abstract val isLateinit: Boolean
abstract val isDelegated: Boolean
abstract val isExpect: Boolean
abstract val isFakeOverride: Boolean
abstract override val isFakeOverride: Boolean
abstract var backingField: IrField?
abstract var getter: IrSimpleFunction?
@@ -12,14 +12,13 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
abstract class IrSimpleFunction :
IrFunction(),
IrOverridableDeclaration<IrSimpleFunctionSymbol>,
IrOverridableMember,
IrAttributeContainer {
abstract override val symbol: IrSimpleFunctionSymbol
abstract val isTailrec: Boolean
abstract val isSuspend: Boolean
abstract val isFakeOverride: Boolean
abstract override val isFakeOverride: Boolean
abstract val isOperator: Boolean
abstract val isInfix: Boolean
@@ -74,7 +74,7 @@ class IrLazyProperty(
override var overriddenSymbols: List<IrPropertySymbol> by lazyVar(stubGenerator.lock) {
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.symbols.*
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.render
import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo
@@ -36,9 +35,6 @@ abstract class FakeOverrideBuilderStrategy {
protected abstract fun linkFunctionFakeOverride(declaration: IrFakeOverrideFunction)
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 {
@@ -89,35 +85,32 @@ class IrOverridingUtil(
originalSuperTypes.clear()
}
private var IrOverridableMember.overriddenSymbols: List<IrSymbol>
get() = when (this) {
is IrSimpleFunction -> this.overriddenSymbols
is IrProperty -> fakeOverrideBuilder.propertyOverriddenSymbols[this]
?: error("No overridden symbols for ${this.render()}")
private val IrOverridableMember.overriddenSymbols: List<IrSymbol>
get() = (this as? IrOverridableDeclaration<*>)?.overriddenSymbols
?: error("Unexpected IrOverridableMember: $this")
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")
}
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) {
val superTypes = clazz.superTypes
@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 superClass = superType.getClass() ?: error("Unexpected super type: $superType")
@@ -147,19 +140,8 @@ class IrOverridingUtil(
clazz: IrClass,
implementedMembers: List<IrOverridableMember> = emptyList()
): List<IrOverridableMember> {
fakeOverrideBuilder.propertyOverriddenSymbols.clear()
val overriddenMembers = (clazz.declarations.filterIsInstance<IrOverridableMember>() + implementedMembers)
.flatMap {
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")
}
}
.flatMap { member -> member.overriddenSymbols.map { it.owner } }
.toSet()
val unoverriddenSuperMembers = clazz.superTypes.flatMap { superType ->
@@ -242,7 +224,7 @@ class IrOverridingUtil(
}
}
//strategy.setOverriddenDescriptors(fromCurrent, overridden)
fromCurrent.overriddenSymbols = overridden.map { it.original.symbol }
fromCurrent.setOverriddenSymbols(overridden.map { it.original.symbol })
return bound
}
@@ -400,7 +382,7 @@ class IrOverridingUtil(
}
}
fakeOverride.overriddenSymbols = effectiveOverridden.map { it.original.symbol }
fakeOverride.setOverriddenSymbols(effectiveOverridden.map { it.original.symbol })
assert(
fakeOverride.overriddenSymbols.isNotEmpty()
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.ir.util
import org.jetbrains.kotlin.descriptors.Modality
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
val IrDeclaration.isReal: Boolean get() = !isFakeOverride
@@ -31,65 +31,50 @@ val IrFunction.target: IrFunction get() = when (this) {
else -> error(this)
}
fun IrSimpleFunction.collectRealOverrides(
toSkip: (IrSimpleFunction) -> Boolean = { false },
filter: (IrOverridableMember) -> Boolean = { false }
): Set<IrSimpleFunction> {
fun <S : IrSymbol, T : IrOverridableDeclaration<S>> T.collectRealOverrides(
toSkip: (T) -> Boolean = { false },
filter: (T) -> Boolean = { false }
): Set<T> {
if (isReal && !toSkip(this)) return setOf(this)
@Suppress("UNCHECKED_CAST")
return this.overriddenSymbols
.map { it.owner }
.collectAndFilterRealOverrides(
{
require(it is IrSimpleFunction) { "Expected IrSimpleFunction: ${it.render()}" }
toSkip(it)
},
filter
) as Set<IrSimpleFunction>
.map { it.owner as T }
.collectAndFilterRealOverrides(toSkip, filter)
}
fun Collection<IrOverridableMember>.collectAndFilterRealOverrides(
toSkip: (IrOverridableMember) -> Boolean = { false },
filter: (IrOverridableMember) -> Boolean = { false },
getOverriddenPropertySymbols: IrProperty.() -> List<IrPropertySymbol> = {
// 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> {
fun <S : IrSymbol, T : IrOverridableDeclaration<S>> Collection<T>.collectAndFilterRealOverrides(
toSkip: (T) -> Boolean = { false },
filter: (T) -> Boolean = { false }
): Set<T> {
val visited = mutableSetOf<IrOverridableMember>()
val realOverrides = mutableMapOf<Any, IrOverridableMember>()
val visited = mutableSetOf<T>()
val realOverrides = mutableMapOf<Any, T>()
/*
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) {
is IrSimpleFunction -> declaration.overriddenSymbols
is IrProperty -> declaration.getOverriddenPropertySymbols()
else -> error("Unexpected overridable member: ${declaration.render()}")
}
fun collectRealOverrides(member: IrOverridableMember) {
fun collectRealOverrides(member: T) {
if (!visited.add(member) || filter(member)) return
if (member.isReal && !toSkip(member)) {
realOverrides[member.toKey()] = member
} else {
overriddenSymbols(member).forEach { collectRealOverrides(it.owner as IrOverridableMember) }
@Suppress("UNCHECKED_CAST")
member.overriddenSymbols.forEach { collectRealOverrides(it.owner as T) }
}
}
this.forEach { collectRealOverrides(it) }
fun excludeRepeated(member: IrOverridableMember) {
fun excludeRepeated(member: T) {
if (!visited.add(member)) return
overriddenSymbols(member).forEach {
val owner = it.owner as IrOverridableMember
member.overriddenSymbols.forEach {
@Suppress("UNCHECKED_CAST")
val owner = it.owner as T
realOverrides.remove(owner.toKey())
excludeRepeated(owner)
}
@@ -101,8 +86,16 @@ fun Collection<IrOverridableMember>.collectAndFilterRealOverrides(
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
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) {
val reals = collectRealOverrides(toSkip)
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 }
}
fun IrProperty.resolveFakeOverride(): IrProperty? = getter?.resolveFakeOverride()?.correspondingPropertySymbol?.owner
val IrClass.isAnnotationClass get() = kind == ClassKind.ANNOTATION_CLASS
val IrClass.isEnumClass get() = kind == ClassKind.ENUM_CLASS
val IrClass.isEnumEntry get() = kind == ClassKind.ENUM_ENTRY
@@ -159,7 +159,6 @@ class FakeOverrideBuilder(
private fun provideFakeOverrides(klass: IrClass) {
buildFakeOverrideChainsForClass(klass)
propertyOverriddenSymbols.clear()
irOverridingUtil.clear()
haveFakeOverrides.add(klass)
}