From fca804de149a9d1789744b39fe734aa68da429a1 Mon Sep 17 00:00:00 2001 From: Georgy Bronnikov Date: Thu, 20 May 2021 21:05:08 +0300 Subject: [PATCH] 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. --- .../jvm/lower/SyntheticAccessorLowering.kt | 4 +- .../kotlin/ir/declarations/IrDeclaration.kt | 4 +- .../kotlin/ir/declarations/IrProperty.kt | 3 +- .../ir/declarations/IrSimpleFunction.kt | 3 +- .../ir/declarations/lazy/IrLazyProperty.kt | 2 +- .../kotlin/ir/overrides/IrOverridingUtil.kt | 62 ++++++----------- .../kotlin/ir/util/IrFakeOverrideUtils.kt | 67 +++++++++---------- .../org/jetbrains/kotlin/ir/util/IrUtils.kt | 2 - .../backend/common/overrides/FakeOverrides.kt | 1 - 9 files changed, 60 insertions(+), 88 deletions(-) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt index 6aa85de7338..7cf10734984 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/lower/SyntheticAccessorLowering.kt @@ -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()}") } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclaration.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclaration.kt index 6326ad900c1..416cd8b7d15 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclaration.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrDeclaration.kt @@ -48,7 +48,9 @@ interface IrDeclaration : IrStatement, IrSymbolOwner, IrMutableAnnotationContain abstract class IrDeclarationBase : IrElementBase(), IrDeclaration -interface IrOverridableDeclaration : IrDeclaration { +interface IrOverridableDeclaration : IrOverridableMember { + override val symbol: S + val isFakeOverride: Boolean var overriddenSymbols: List } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrProperty.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrProperty.kt index a32f28e1f6f..d131f3d1773 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrProperty.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrProperty.kt @@ -25,7 +25,6 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitor abstract class IrProperty : IrDeclarationBase(), IrPossiblyExternalDeclaration, - IrOverridableMember, IrOverridableDeclaration, 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? diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrSimpleFunction.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrSimpleFunction.kt index 78caf32b5fc..0acfc3918bb 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrSimpleFunction.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/IrSimpleFunction.kt @@ -12,14 +12,13 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitor abstract class IrSimpleFunction : IrFunction(), IrOverridableDeclaration, - 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 diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyProperty.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyProperty.kt index 33764a18643..fb4d739295d 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyProperty.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/declarations/lazy/IrLazyProperty.kt @@ -74,7 +74,7 @@ class IrLazyProperty( override var overriddenSymbols: List by lazyVar(stubGenerator.lock) { descriptor.overriddenDescriptors.mapTo(ArrayList()) { - stubGenerator.generatePropertyStub(it).symbol + stubGenerator.generatePropertyStub(it.original).symbol } } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/overrides/IrOverridingUtil.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/overrides/IrOverridingUtil.kt index 10d2ee41257..1439340e487 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/overrides/IrOverridingUtil.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/overrides/IrOverridingUtil.kt @@ -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> = mutableMapOf() } fun buildFakeOverrideMember(superType: IrType, member: IrOverridableMember, clazz: IrClass): IrOverridableMember { @@ -89,35 +85,32 @@ class IrOverridingUtil( originalSuperTypes.clear() } - private var IrOverridableMember.overriddenSymbols: List - get() = when (this) { - is IrSimpleFunction -> this.overriddenSymbols - is IrProperty -> fakeOverrideBuilder.propertyOverriddenSymbols[this] - ?: error("No overridden symbols for ${this.render()}") + private val IrOverridableMember.overriddenSymbols: List + get() = (this as? IrOverridableDeclaration<*>)?.overriddenSymbols + ?: error("Unexpected IrOverridableMember: $this") + + private fun IrOverridableMember.setOverriddenSymbols(value: List) { + 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 + val fromCurrent = clazz.declarations.filterIsInstance() val allFromSuper = superTypes.flatMap { superType -> val superClass = superType.getClass() ?: error("Unexpected super type: $superType") @@ -147,19 +140,8 @@ class IrOverridingUtil( clazz: IrClass, implementedMembers: List = emptyList() ): List { - fakeOverrideBuilder.propertyOverriddenSymbols.clear() - val overriddenMembers = (clazz.declarations.filterIsInstance() + 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() 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 08ff88b5357..8b0003ff2b2 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 @@ -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 { +fun > T.collectRealOverrides( + toSkip: (T) -> Boolean = { false }, + filter: (T) -> Boolean = { false } +): Set { 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 + .map { it.owner as T } + .collectAndFilterRealOverrides(toSkip, filter) } -fun Collection.collectAndFilterRealOverrides( - toSkip: (IrOverridableMember) -> Boolean = { false }, - filter: (IrOverridableMember) -> Boolean = { false }, - getOverriddenPropertySymbols: IrProperty.() -> List = { - // 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 { +fun > Collection.collectAndFilterRealOverrides( + toSkip: (T) -> Boolean = { false }, + filter: (T) -> Boolean = { false } +): Set { - val visited = mutableSetOf() - val realOverrides = mutableMapOf() + val visited = mutableSetOf() + val realOverrides = mutableMapOf() /* 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.collectAndFilterRealOverrides( return realOverrides.values.toSet() } +fun Collection.collectAndFilterRealOverrides(): Set = + @Suppress("UNCHECKED_CAST") + (this as Collection>).collectAndFilterRealOverrides() + // TODO: use this implementation instead of any other -fun IrSimpleFunction.resolveFakeOverride(allowAbstract: Boolean = false, toSkip: (IrSimpleFunction) -> Boolean = { false }): IrSimpleFunction? { +fun > 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()}") diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt index e715875dd11..fabe3b68f02 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt @@ -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 diff --git a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/overrides/FakeOverrides.kt b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/overrides/FakeOverrides.kt index ef52d167751..34d83db357b 100644 --- a/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/overrides/FakeOverrides.kt +++ b/compiler/ir/serialization.common/src/org/jetbrains/kotlin/backend/common/overrides/FakeOverrides.kt @@ -159,7 +159,6 @@ class FakeOverrideBuilder( private fun provideFakeOverrides(klass: IrClass) { buildFakeOverrideChainsForClass(klass) - propertyOverriddenSymbols.clear() irOverridingUtil.clear() haveFakeOverrides.add(klass) }