FIR2IR: delay generation of delegated member bodies

Before this commit, we generated delegated member bodies eagerly
at the moment when delegated member itself was generated.
However, in fact delegated member may access e.g. fake override inside
its body, so to work properly, we must delay body generation.
This commit is contained in:
Mikhail Glukhikh
2021-12-02 18:36:30 +03:00
parent 85240bdb06
commit 49bb2a578e
3 changed files with 48 additions and 22 deletions
@@ -103,6 +103,7 @@ class Fir2IrConverter(
// 5. Body processing // 5. Body processing
// If we encounter local class / anonymous object here, then we perform all (1)-(5) stages immediately // If we encounter local class / anonymous object here, then we perform all (1)-(5) stages immediately
delegatedMemberGenerator.generateBodies()
for (firFile in allFirFiles) { for (firFile in allFirFiles) {
firFile.accept(fir2irVisitor, null) firFile.accept(fir2irVisitor, null)
} }
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyConstructor
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyProperty import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyProperty
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazySimpleFunction import org.jetbrains.kotlin.fir.lazy.Fir2IrLazySimpleFunction
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.isLocalClassOrAnonymousObject
import org.jetbrains.kotlin.fir.types.isSuspendFunctionType import org.jetbrains.kotlin.fir.types.isSuspendFunctionType
import org.jetbrains.kotlin.fir.resolve.isKFunctionInvoke import org.jetbrains.kotlin.fir.resolve.isKFunctionInvoke
import org.jetbrains.kotlin.fir.resolve.providers.firProvider import org.jetbrains.kotlin.fir.resolve.providers.firProvider
@@ -949,7 +950,10 @@ class Fir2IrDeclarationStorage(
fun createIrFieldAndDelegatedMembers(field: FirField, owner: FirClass, irClass: IrClass): IrField { fun createIrFieldAndDelegatedMembers(field: FirField, owner: FirClass, irClass: IrClass): IrField {
val irField = createIrField(field, origin = IrDeclarationOrigin.DELEGATE) val irField = createIrField(field, origin = IrDeclarationOrigin.DELEGATE)
irField.setAndModifyParent(irClass) irField.setAndModifyParent(irClass)
components.delegatedMemberGenerator.generate(irField, field, owner, irClass) delegatedMemberGenerator.generate(irField, field, owner, irClass)
if (owner.isLocalClassOrAnonymousObject()) {
delegatedMemberGenerator.generateBodies()
}
return irField return irField
} }
@@ -50,6 +50,40 @@ class DelegatedMemberGenerator(
private val baseFunctionSymbols = mutableMapOf<IrFunction, List<FirNamedFunctionSymbol>>() private val baseFunctionSymbols = mutableMapOf<IrFunction, List<FirNamedFunctionSymbol>>()
private val basePropertySymbols = mutableMapOf<IrProperty, List<FirPropertySymbol>>() private val basePropertySymbols = mutableMapOf<IrProperty, List<FirPropertySymbol>>()
private data class DeclarationBodyInfo(
val declaration: IrDeclaration,
val field: IrField,
val delegateToSymbol: FirCallableSymbol<*>
)
private val bodiesInfo = mutableListOf<DeclarationBodyInfo>()
fun generateBodies() {
for ((declaration, irField, delegateToSymbol) in bodiesInfo) {
when (declaration) {
is IrSimpleFunction -> {
val member = declarationStorage.getIrFunctionSymbol(
delegateToSymbol as FirNamedFunctionSymbol
).owner as? IrSimpleFunction ?: continue
val body = createDelegateBody(irField, declaration, member)
declaration.body = body
}
is IrProperty -> {
val member = declarationStorage.getIrPropertySymbol(
delegateToSymbol as FirPropertySymbol
).owner as? IrProperty ?: continue
val getter = declaration.getter!!
getter.body = createDelegateBody(irField, getter, member.getter!!)
if (declaration.isVar) {
val setter = declaration.setter!!
setter.body = createDelegateBody(irField, setter, member.setter!!)
}
}
}
}
bodiesInfo.clear()
}
// Generate delegated members for [subClass]. The synthetic field [irField] has the super interface type. // Generate delegated members for [subClass]. The synthetic field [irField] has the super interface type.
fun generate(irField: IrField, firField: FirField, firSubClass: FirClass, subClass: IrClass) { fun generate(irField: IrField, firField: FirField, firSubClass: FirClass, subClass: IrClass) {
val subClassLookupTag = firSubClass.symbol.toLookupTag() val subClassLookupTag = firSubClass.symbol.toLookupTag()
@@ -61,18 +95,14 @@ class DelegatedMemberGenerator(
.unwrapDelegateTarget(subClassLookupTag, firField) .unwrapDelegateTarget(subClassLookupTag, firField)
?: return@processAllFunctions ?: return@processAllFunctions
val member =
declarationStorage.getIrFunctionSymbol(unwrapped.symbol).owner as? IrSimpleFunction
?: return@processAllFunctions
if (shouldSkipDelegationFor(unwrapped)) { if (shouldSkipDelegationFor(unwrapped)) {
return@processAllFunctions return@processAllFunctions
} }
val irSubFunction = generateDelegatedFunction( val irSubFunction = generateDelegatedFunction(
subClass, firSubClass, irField, member, functionSymbol.fir subClass, firSubClass, functionSymbol.fir
) )
bodiesInfo += DeclarationBodyInfo(irSubFunction, irField, unwrapped.symbol)
declarationStorage.cacheDelegationFunction(functionSymbol.fir, irSubFunction) declarationStorage.cacheDelegationFunction(functionSymbol.fir, irSubFunction)
subClass.addMember(irSubFunction) subClass.addMember(irSubFunction)
} }
@@ -85,17 +115,14 @@ class DelegatedMemberGenerator(
.unwrapDelegateTarget(subClassLookupTag, firField) .unwrapDelegateTarget(subClassLookupTag, firField)
?: return@processAllProperties ?: return@processAllProperties
val member = declarationStorage.getIrPropertySymbol(unwrapped.symbol).owner as? IrProperty
?: return@processAllProperties
if (shouldSkipDelegationFor(unwrapped)) { if (shouldSkipDelegationFor(unwrapped)) {
return@processAllProperties return@processAllProperties
} }
val irSubProperty = generateDelegatedProperty( val irSubProperty = generateDelegatedProperty(
subClass, firSubClass, irField, member, propertySymbol.fir subClass, firSubClass, propertySymbol.fir
) )
bodiesInfo += DeclarationBodyInfo(irSubProperty, irField, unwrapped.symbol)
declarationStorage.cacheDelegatedProperty(propertySymbol.fir, irSubProperty) declarationStorage.cacheDelegatedProperty(propertySymbol.fir, irSubProperty)
subClass.addMember(irSubProperty) subClass.addMember(irSubProperty)
} }
@@ -146,8 +173,6 @@ class DelegatedMemberGenerator(
private fun generateDelegatedFunction( private fun generateDelegatedFunction(
subClass: IrClass, subClass: IrClass,
firSubClass: FirClass, firSubClass: FirClass,
irField: IrField,
superFunction: IrSimpleFunction,
delegateOverride: FirSimpleFunction delegateOverride: FirSimpleFunction
): IrSimpleFunction { ): IrSimpleFunction {
val delegateFunction = val delegateFunction =
@@ -164,8 +189,6 @@ class DelegatedMemberGenerator(
baseFunctionSymbols[delegateFunction] = baseSymbols baseFunctionSymbols[delegateFunction] = baseSymbols
annotationGenerator.generate(delegateFunction, delegateOverride) annotationGenerator.generate(delegateFunction, delegateOverride)
val body = createDelegateBody(irField, delegateFunction, superFunction)
delegateFunction.body = body
return delegateFunction return delegateFunction
} }
@@ -226,8 +249,6 @@ class DelegatedMemberGenerator(
private fun generateDelegatedProperty( private fun generateDelegatedProperty(
subClass: IrClass, subClass: IrClass,
firSubClass: FirClass, firSubClass: FirClass,
irField: IrField,
superProperty: IrProperty,
firDelegateProperty: FirProperty firDelegateProperty: FirProperty
): IrProperty { ): IrProperty {
val delegateProperty = val delegateProperty =
@@ -244,8 +265,8 @@ class DelegatedMemberGenerator(
basePropertySymbols[delegateProperty] = baseSymbols basePropertySymbols[delegateProperty] = baseSymbols
annotationGenerator.generate(delegateProperty, firDelegateProperty) annotationGenerator.generate(delegateProperty, firDelegateProperty)
delegateProperty.getter!!.body = createDelegateBody(irField, delegateProperty.getter!!, superProperty.getter!!) val getter = delegateProperty.getter!!
delegateProperty.getter!!.overriddenSymbols = getter.overriddenSymbols =
firDelegateProperty.generateOverriddenAccessorSymbols( firDelegateProperty.generateOverriddenAccessorSymbols(
firSubClass, firSubClass,
isGetter = true, isGetter = true,
@@ -256,8 +277,8 @@ class DelegatedMemberGenerator(
) )
annotationGenerator.generate(delegateProperty.getter!!, firDelegateProperty) annotationGenerator.generate(delegateProperty.getter!!, firDelegateProperty)
if (delegateProperty.isVar) { if (delegateProperty.isVar) {
delegateProperty.setter!!.body = createDelegateBody(irField, delegateProperty.setter!!, superProperty.setter!!) val setter = delegateProperty.setter!!
delegateProperty.setter!!.overriddenSymbols = setter.overriddenSymbols =
firDelegateProperty.generateOverriddenAccessorSymbols( firDelegateProperty.generateOverriddenAccessorSymbols(
firSubClass, isGetter = false, session, scopeSession, declarationStorage, fakeOverrideGenerator firSubClass, isGetter = false, session, scopeSession, declarationStorage, fakeOverrideGenerator
) )