From 49bb2a578ef0c6881a17340e5d0804bbfe0b5d19 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Thu, 2 Dec 2021 18:36:30 +0300 Subject: [PATCH] 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. --- .../kotlin/fir/backend/Fir2IrConverter.kt | 1 + .../fir/backend/Fir2IrDeclarationStorage.kt | 6 +- .../generators/DelegatedMemberGenerator.kt | 63 ++++++++++++------- 3 files changed, 48 insertions(+), 22 deletions(-) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt index 0d38c47d9ab..81eb6a18303 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt @@ -103,6 +103,7 @@ class Fir2IrConverter( // 5. Body processing // If we encounter local class / anonymous object here, then we perform all (1)-(5) stages immediately + delegatedMemberGenerator.generateBodies() for (firFile in allFirFiles) { firFile.accept(fir2irVisitor, null) } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt index 3d900cbe4f5..0d640d73806 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt @@ -30,6 +30,7 @@ import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyConstructor import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyProperty import org.jetbrains.kotlin.fir.lazy.Fir2IrLazySimpleFunction 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.resolve.isKFunctionInvoke import org.jetbrains.kotlin.fir.resolve.providers.firProvider @@ -949,7 +950,10 @@ class Fir2IrDeclarationStorage( fun createIrFieldAndDelegatedMembers(field: FirField, owner: FirClass, irClass: IrClass): IrField { val irField = createIrField(field, origin = IrDeclarationOrigin.DELEGATE) irField.setAndModifyParent(irClass) - components.delegatedMemberGenerator.generate(irField, field, owner, irClass) + delegatedMemberGenerator.generate(irField, field, owner, irClass) + if (owner.isLocalClassOrAnonymousObject()) { + delegatedMemberGenerator.generateBodies() + } return irField } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DelegatedMemberGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DelegatedMemberGenerator.kt index eef290d7361..629e711d04f 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DelegatedMemberGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DelegatedMemberGenerator.kt @@ -50,6 +50,40 @@ class DelegatedMemberGenerator( private val baseFunctionSymbols = mutableMapOf>() private val basePropertySymbols = mutableMapOf>() + private data class DeclarationBodyInfo( + val declaration: IrDeclaration, + val field: IrField, + val delegateToSymbol: FirCallableSymbol<*> + ) + + private val bodiesInfo = mutableListOf() + + 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. fun generate(irField: IrField, firField: FirField, firSubClass: FirClass, subClass: IrClass) { val subClassLookupTag = firSubClass.symbol.toLookupTag() @@ -61,18 +95,14 @@ class DelegatedMemberGenerator( .unwrapDelegateTarget(subClassLookupTag, firField) ?: return@processAllFunctions - val member = - declarationStorage.getIrFunctionSymbol(unwrapped.symbol).owner as? IrSimpleFunction - ?: return@processAllFunctions - if (shouldSkipDelegationFor(unwrapped)) { return@processAllFunctions } val irSubFunction = generateDelegatedFunction( - subClass, firSubClass, irField, member, functionSymbol.fir + subClass, firSubClass, functionSymbol.fir ) - + bodiesInfo += DeclarationBodyInfo(irSubFunction, irField, unwrapped.symbol) declarationStorage.cacheDelegationFunction(functionSymbol.fir, irSubFunction) subClass.addMember(irSubFunction) } @@ -85,17 +115,14 @@ class DelegatedMemberGenerator( .unwrapDelegateTarget(subClassLookupTag, firField) ?: return@processAllProperties - val member = declarationStorage.getIrPropertySymbol(unwrapped.symbol).owner as? IrProperty - ?: return@processAllProperties - if (shouldSkipDelegationFor(unwrapped)) { return@processAllProperties } val irSubProperty = generateDelegatedProperty( - subClass, firSubClass, irField, member, propertySymbol.fir + subClass, firSubClass, propertySymbol.fir ) - + bodiesInfo += DeclarationBodyInfo(irSubProperty, irField, unwrapped.symbol) declarationStorage.cacheDelegatedProperty(propertySymbol.fir, irSubProperty) subClass.addMember(irSubProperty) } @@ -146,8 +173,6 @@ class DelegatedMemberGenerator( private fun generateDelegatedFunction( subClass: IrClass, firSubClass: FirClass, - irField: IrField, - superFunction: IrSimpleFunction, delegateOverride: FirSimpleFunction ): IrSimpleFunction { val delegateFunction = @@ -164,8 +189,6 @@ class DelegatedMemberGenerator( baseFunctionSymbols[delegateFunction] = baseSymbols annotationGenerator.generate(delegateFunction, delegateOverride) - val body = createDelegateBody(irField, delegateFunction, superFunction) - delegateFunction.body = body return delegateFunction } @@ -226,8 +249,6 @@ class DelegatedMemberGenerator( private fun generateDelegatedProperty( subClass: IrClass, firSubClass: FirClass, - irField: IrField, - superProperty: IrProperty, firDelegateProperty: FirProperty ): IrProperty { val delegateProperty = @@ -244,8 +265,8 @@ class DelegatedMemberGenerator( basePropertySymbols[delegateProperty] = baseSymbols annotationGenerator.generate(delegateProperty, firDelegateProperty) - delegateProperty.getter!!.body = createDelegateBody(irField, delegateProperty.getter!!, superProperty.getter!!) - delegateProperty.getter!!.overriddenSymbols = + val getter = delegateProperty.getter!! + getter.overriddenSymbols = firDelegateProperty.generateOverriddenAccessorSymbols( firSubClass, isGetter = true, @@ -256,8 +277,8 @@ class DelegatedMemberGenerator( ) annotationGenerator.generate(delegateProperty.getter!!, firDelegateProperty) if (delegateProperty.isVar) { - delegateProperty.setter!!.body = createDelegateBody(irField, delegateProperty.setter!!, superProperty.setter!!) - delegateProperty.setter!!.overriddenSymbols = + val setter = delegateProperty.setter!! + setter.overriddenSymbols = firDelegateProperty.generateOverriddenAccessorSymbols( firSubClass, isGetter = false, session, scopeSession, declarationStorage, fakeOverrideGenerator )