Skip to content

Commit

Permalink
IR: properly compute IrProperty.resolveFakeOverride()
Browse files Browse the repository at this point in the history
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.

(cherry picked from commit fca804d)
  • Loading branch information
Georgy Bronnikov authored and Space committed Jul 6, 2021
1 parent a1e6c87 commit 3843893
Show file tree
Hide file tree
Showing 9 changed files with 59 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -770,8 +770,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()}")
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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>
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
abstract class IrProperty :
IrDeclarationBase(),
IrPossiblyExternalDeclaration,
IrOverridableMember,
IrOverridableDeclaration<IrPropertySymbol>,
IrMetadataSourceOwner,
IrAttributeContainer,
Expand All @@ -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?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 {
Expand Down Expand Up @@ -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()}")
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 }
}
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")
}
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")
Expand Down Expand Up @@ -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 ->
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -400,7 +382,7 @@ class IrOverridingUtil(
}
}

fakeOverride.overriddenSymbols = effectiveOverridden.map { it.original.symbol }
fakeOverride.setOverriddenSymbols(effectiveOverridden.map { it.original.symbol })

assert(
fakeOverride.overriddenSymbols.isNotEmpty()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
}
Expand All @@ -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()}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,6 @@ class FakeOverrideBuilder(

private fun provideFakeOverrides(klass: IrClass) {
buildFakeOverrideChainsForClass(klass)
propertyOverriddenSymbols.clear()
irOverridingUtil.clear()
haveFakeOverrides.add(klass)
}
Expand Down

0 comments on commit 3843893

Please sign in to comment.