IR: Fix fake-override resolution for fields
Earlier we used a result of a corresponding getter resolution to obtain a fake overridden field. This approach is incorrect because the getter resolved may not contain a backing field. This patch fixes the issue by using the overriddenSymbols property of an IrField directly. Issue #KT-33034 fixed
This commit is contained in:
@@ -210,11 +210,11 @@ val IrBody.statements: List<IrStatement>
|
|||||||
val IrClass.defaultType: IrSimpleType
|
val IrClass.defaultType: IrSimpleType
|
||||||
get() = this.thisReceiver!!.type as IrSimpleType
|
get() = this.thisReceiver!!.type as IrSimpleType
|
||||||
|
|
||||||
val IrSimpleFunction.isReal: Boolean get() = descriptor.kind.isReal
|
|
||||||
|
|
||||||
val IrSimpleFunction.isSynthesized: Boolean get() = descriptor.kind == CallableMemberDescriptor.Kind.SYNTHESIZED
|
val IrSimpleFunction.isSynthesized: Boolean get() = descriptor.kind == CallableMemberDescriptor.Kind.SYNTHESIZED
|
||||||
|
|
||||||
val IrSimpleFunction.isFakeOverride: Boolean get() = origin == IrDeclarationOrigin.FAKE_OVERRIDE
|
val IrDeclaration.isReal: Boolean get() = !isFakeOverride
|
||||||
|
|
||||||
|
val IrDeclaration.isFakeOverride: Boolean get() = origin == IrDeclarationOrigin.FAKE_OVERRIDE
|
||||||
|
|
||||||
fun IrClass.isSubclassOf(ancestor: IrClass): Boolean {
|
fun IrClass.isSubclassOf(ancestor: IrClass): Boolean {
|
||||||
|
|
||||||
|
|||||||
+43
-23
@@ -7,30 +7,27 @@ package org.jetbrains.kotlin.backend.common.serialization
|
|||||||
|
|
||||||
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.IrBindableSymbol
|
||||||
import org.jetbrains.kotlin.ir.util.isReal
|
import org.jetbrains.kotlin.ir.util.isReal
|
||||||
import org.jetbrains.kotlin.ir.util.original
|
import org.jetbrains.kotlin.ir.util.original
|
||||||
|
|
||||||
|
// We may get several real supers here (e.g. see the code snippet from KT-33034).
|
||||||
/**
|
// TODO: Consider reworking the resolution algorithm to get a determined super declaration.
|
||||||
* Implementation of given method.
|
private fun <S: IrBindableSymbol<*, D>, D: IrOverridableDeclaration<S>> D.getRealSupers(): Set<D> {
|
||||||
*
|
|
||||||
* TODO: this method is actually a part of resolve and probably duplicates another one
|
|
||||||
*/
|
|
||||||
fun IrSimpleFunction.resolveFakeOverride(allowAbstract: Boolean = false): IrSimpleFunction {
|
|
||||||
if (this.isReal) {
|
if (this.isReal) {
|
||||||
return this
|
return setOf(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
val visited = mutableSetOf<IrSimpleFunction>()
|
val visited = mutableSetOf<D>()
|
||||||
val realSupers = mutableSetOf<IrSimpleFunction>()
|
val realSupers = mutableSetOf<D>()
|
||||||
|
|
||||||
fun findRealSupers(function: IrSimpleFunction) {
|
fun findRealSupers(declaration: D) {
|
||||||
if (function in visited) return
|
if (declaration in visited) return
|
||||||
visited += function
|
visited += declaration
|
||||||
if (function.isReal) {
|
if (declaration.isReal) {
|
||||||
realSupers += function
|
realSupers += declaration
|
||||||
} else {
|
} else {
|
||||||
function.overriddenSymbols.forEach { findRealSupers(it.owner) }
|
declaration.overriddenSymbols.forEach { findRealSupers(it.owner) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,10 +36,10 @@ fun IrSimpleFunction.resolveFakeOverride(allowAbstract: Boolean = false): IrSimp
|
|||||||
if (realSupers.size > 1) {
|
if (realSupers.size > 1) {
|
||||||
visited.clear()
|
visited.clear()
|
||||||
|
|
||||||
fun excludeOverridden(function: IrSimpleFunction) {
|
fun excludeOverridden(declaration: D) {
|
||||||
if (function in visited) return
|
if (declaration in visited) return
|
||||||
visited += function
|
visited += declaration
|
||||||
function.overriddenSymbols.forEach {
|
declaration.overriddenSymbols.forEach {
|
||||||
realSupers.remove(it.owner)
|
realSupers.remove(it.owner)
|
||||||
excludeOverridden(it.owner)
|
excludeOverridden(it.owner)
|
||||||
}
|
}
|
||||||
@@ -51,7 +48,22 @@ fun IrSimpleFunction.resolveFakeOverride(allowAbstract: Boolean = false): IrSimp
|
|||||||
realSupers.toList().forEach { excludeOverridden(it) }
|
realSupers.toList().forEach { excludeOverridden(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
return realSupers.first { allowAbstract || it.modality != Modality.ABSTRACT }
|
return realSupers
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of given method.
|
||||||
|
*
|
||||||
|
* TODO: this method is actually a part of resolve and probably duplicates another one
|
||||||
|
*/
|
||||||
|
fun IrSimpleFunction.resolveFakeOverride(allowAbstract: Boolean = false): IrSimpleFunction {
|
||||||
|
val realSupers = getRealSupers()
|
||||||
|
|
||||||
|
return if (allowAbstract) {
|
||||||
|
realSupers.first()
|
||||||
|
} else {
|
||||||
|
realSupers.single { it.modality != Modality.ABSTRACT }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -61,9 +73,17 @@ fun IrSimpleFunction.resolveFakeOverride(allowAbstract: Boolean = false): IrSimp
|
|||||||
*/
|
*/
|
||||||
internal fun IrSimpleFunction.resolveFakeOverrideMaybeAbstract() = this.resolveFakeOverride(allowAbstract = true)
|
internal fun IrSimpleFunction.resolveFakeOverrideMaybeAbstract() = this.resolveFakeOverride(allowAbstract = true)
|
||||||
|
|
||||||
internal fun IrProperty.resolveFakeOverrideMaybeAbstract() = this.getter!!.resolveFakeOverrideMaybeAbstract().correspondingProperty!!
|
internal fun IrProperty.resolveFakeOverrideMaybeAbstract(): IrProperty =
|
||||||
|
this.getter!!.resolveFakeOverrideMaybeAbstract().correspondingPropertySymbol!!.owner
|
||||||
|
|
||||||
internal fun IrField.resolveFakeOverrideMaybeAbstract() = this.correspondingProperty!!.getter!!.resolveFakeOverrideMaybeAbstract().correspondingProperty!!.backingField
|
/**
|
||||||
|
* TODO: This method can be simplified if the "overriddenSymbols" list of an IrField always includes only one element.
|
||||||
|
* Currently it's not the case for some cinterop libraries (e.g. Foundation). In these libraries interfaces containing
|
||||||
|
* final properties with external getters are created (corresponding compiler error is suppressed). Due to KT-33081
|
||||||
|
* such a property gets a backing field and a field of a class implementing such interfaces can have several elements
|
||||||
|
* in the overriddenSymbols list.
|
||||||
|
*/
|
||||||
|
internal fun IrField.resolveFakeOverride(): IrField = getRealSupers().first()
|
||||||
|
|
||||||
val IrSimpleFunction.target: IrSimpleFunction
|
val IrSimpleFunction.target: IrSimpleFunction
|
||||||
get() = (if (modality == Modality.ABSTRACT) this else resolveFakeOverride()).original
|
get() = (if (modality == Modality.ABSTRACT) this else resolveFakeOverride()).original
|
||||||
|
|||||||
+1
-1
@@ -78,7 +78,7 @@ open class DescriptorReferenceSerializer(
|
|||||||
val realDeclaration = if (isFakeOverride) {
|
val realDeclaration = if (isFakeOverride) {
|
||||||
when (declaration) {
|
when (declaration) {
|
||||||
is IrSimpleFunction -> declaration.resolveFakeOverrideMaybeAbstract()
|
is IrSimpleFunction -> declaration.resolveFakeOverrideMaybeAbstract()
|
||||||
is IrField -> declaration.resolveFakeOverrideMaybeAbstract()
|
is IrField -> declaration.resolveFakeOverride()
|
||||||
is IrProperty -> declaration.resolveFakeOverrideMaybeAbstract()
|
is IrProperty -> declaration.resolveFakeOverrideMaybeAbstract()
|
||||||
else -> error("Unexpected fake override declaration")
|
else -> error("Unexpected fake override declaration")
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user