From fb4b14e250f20f9c49b3aec97c87d1bba4963f13 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Wed, 21 Feb 2024 11:11:55 +0200 Subject: [PATCH] [FIR2IR] Part 4. Cleanup Fir2IrClassifierStorage API (enum entries) ^KT-65937 Fixed --- .../fir/backend/Fir2IrClassifierStorage.kt | 33 ++++++++++++------- .../fir/backend/Fir2IrCommonMemberStorage.kt | 2 +- .../kotlin/fir/backend/Fir2IrConverter.kt | 6 ++-- .../fir/backend/Fir2IrDeclarationStorage.kt | 24 +++----------- .../kotlin/fir/backend/Fir2IrVisitor.kt | 10 +++--- .../kotlin/fir/backend/FirIrProvider.kt | 7 ++-- .../kotlin/fir/lazy/Fir2IrLazyClass.kt | 2 +- .../selfReferentialAnnotation.fir.ir.txt | 4 +-- .../annotations/selfReferentialAnnotation.kt | 1 - 9 files changed, 43 insertions(+), 46 deletions(-) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt index 669de38eafb..9378996c27c 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrClassifierStorage.kt @@ -41,7 +41,7 @@ class Fir2IrClassifierStorage( private val typeParameterCacheForSetter: MutableMap = mutableMapOf() - private val enumEntryCache: MutableMap = commonMemberStorage.enumEntryCache + private val enumEntryCache: MutableMap = commonMemberStorage.enumEntryCache private val codeFragmentCache: MutableMap = mutableMapOf() @@ -64,7 +64,7 @@ class Fir2IrClassifierStorage( fun forEachCachedDeclarationSymbol(block: (IrSymbol) -> Unit) { classCache.values.forEach { block(it) } typeAliasCache.values.forEach { block(it.symbol) } - enumEntryCache.values.forEach { block(it.symbol) } + enumEntryCache.values.forEach { block(it) } fieldsForContextReceivers.values.forEach { fields -> fields.forEach { block(it.symbol) } } @@ -332,17 +332,30 @@ class Fir2IrClassifierStorage( localStorage[(enumEntry.initializer as FirAnonymousObjectExpression).anonymousObject] = correspondingClass } - internal fun getCachedIrEnumEntry(enumEntry: FirEnumEntry): IrEnumEntry? { - return enumEntryCache[enumEntry] + fun getIrEnumEntrySymbol(enumEntry: FirEnumEntry): IrEnumEntrySymbol { + enumEntryCache[enumEntry]?.let { return it } + + val symbol = IrEnumEntrySymbolImpl() + enumEntryCache[enumEntry] = symbol + + val irParent = declarationStorage.findIrParent(enumEntry, fakeOverrideOwnerLookupTag = null) as IrClass + if (irParent.isExternalParent()) { + classifiersGenerator.createIrEnumEntry( + enumEntry, + irParent = irParent, + symbol, + predefinedOrigin = irParent.origin + ) + } + return symbol } - fun getOrCreateIrEnumEntry( + fun createAndCacheIrEnumEntry( enumEntry: FirEnumEntry, irParent: IrClass, predefinedOrigin: IrDeclarationOrigin? = null, ): IrEnumEntry { - getCachedIrEnumEntry(enumEntry)?.let { return it } - + val symbol = getIrEnumEntrySymbol(enumEntry) val containingFile = firProvider.getFirCallableContainerFile(enumEntry.symbol) @Suppress("NAME_SHADOWING") @@ -351,15 +364,13 @@ class Fir2IrClassifierStorage( } else { irParent.origin } - val symbol = IrEnumEntrySymbolImpl() + return classifiersGenerator.createIrEnumEntry( enumEntry, irParent = irParent, symbol, predefinedOrigin = predefinedOrigin - ).also { - enumEntryCache[enumEntry] = it - } + ) } // ------------------------------------ typealiases ------------------------------------ diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrCommonMemberStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrCommonMemberStorage.kt index 01b47946914..bcfdd786c39 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrCommonMemberStorage.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrCommonMemberStorage.kt @@ -30,7 +30,7 @@ class Fir2IrCommonMemberStorage(firMangler: FirMangler) { val typeParameterCache: MutableMap = mutableMapOf() - val enumEntryCache: MutableMap = mutableMapOf() + val enumEntryCache: MutableMap = mutableMapOf() val localClassCache: MutableMap = mutableMapOf() 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 e1c6cc4f24d..038cb1958d5 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 @@ -462,7 +462,7 @@ class Fir2IrConverter( private fun processClassAndNestedClassHeaders(klass: FirClass) { classifiersGenerator.processClassHeader(klass) processNestedClassHeaders(klass) - val irClass = classifierStorage.getIrClass(klass)!! + val irClass = classifierStorage.getIrClass(klass) /* * This is needed to preserve the source order of declarations in the class * IrClass should contain declarations in the source order, but creating of nested IrClass automatically adds created class to the list @@ -521,7 +521,7 @@ class Fir2IrConverter( val isInLocalClass = containingClass != null && (containingClass !is FirRegularClass || containingClass.isLocal) when (declaration) { is FirRegularClass -> { - val irClass = classifierStorage.getIrClass(declaration)!! + val irClass = classifierStorage.getIrClass(declaration) addDeclarationToParentIfNeeded(irClass) processClassMembers(declaration, irClass) } @@ -594,7 +594,7 @@ class Fir2IrConverter( declarationStorage.createAndCacheIrConstructor(declaration, { parent as IrClass }, isLocal = isInLocalClass) } is FirEnumEntry -> { - classifierStorage.getOrCreateIrEnumEntry(declaration, parent as IrClass) + classifierStorage.createAndCacheIrEnumEntry(declaration, parent as IrClass) } is FirAnonymousInitializer -> { declarationStorage.createIrAnonymousInitializer(declaration, parent as IrClass) 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 94133a648c3..77bd693bf59 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 @@ -992,26 +992,12 @@ class Fir2IrDeclarationStorage( fun getIrValueSymbol(firVariableSymbol: FirVariableSymbol<*>): IrSymbol { return when (val firDeclaration = firVariableSymbol.fir) { - is FirEnumEntry -> { - classifierStorage.getCachedIrEnumEntry(firDeclaration)?.let { return it.symbol } - val irParentClass = firDeclaration.containingClassLookupTag()?.let { classifierStorage.getIrClass(it) }!! + is FirEnumEntry -> classifierStorage.getIrEnumEntrySymbol(firDeclaration) - val containingFile = firProvider.getFirCallableContainerFile(firVariableSymbol) + is FirValueParameter -> localStorage.getParameter(firDeclaration) + ?: getIrVariableSymbol(firDeclaration) // catch parameter is FirValueParameter in FIR but IrVariable in IR - classifierStorage.getOrCreateIrEnumEntry( - firDeclaration, - irParent = irParentClass, - predefinedOrigin = if (containingFile != null) IrDeclarationOrigin.DEFINED else irParentClass.origin - ).symbol - } - is FirValueParameter -> { - localStorage.getParameter(firDeclaration) - // catch parameter is FirValueParameter in FIR but IrVariable in IR - ?: return getIrVariableSymbol(firDeclaration) - } - else -> { - getIrVariableSymbol(firDeclaration) - } + else -> getIrVariableSymbol(firDeclaration) } } @@ -1498,7 +1484,7 @@ class Fir2IrDeclarationStorage( return parentPackage } - private fun findIrParent( + internal fun findIrParent( callableDeclaration: FirCallableDeclaration, fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag?, ): IrDeclarationParent? { diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt index f70d875d0d7..19aaab2c0fb 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrVisitor.kt @@ -126,7 +126,9 @@ class Fir2IrVisitor( } override fun visitEnumEntry(enumEntry: FirEnumEntry, data: Any?): IrElement = whileAnalysing(session, enumEntry) { - val irEnumEntry = classifierStorage.getCachedIrEnumEntry(enumEntry)!! + // At this point all IR for source enum entries should be created and bound to symbols + @OptIn(UnsafeDuringIrConstructionAPI::class) + val irEnumEntry = classifierStorage.getIrEnumEntrySymbol(enumEntry).owner annotationGenerator.generate(irEnumEntry, enumEntry) val correspondingClass = irEnumEntry.correspondingClass val initializer = enumEntry.initializer @@ -191,7 +193,7 @@ class Fir2IrVisitor( if (regularClass.visibility == Visibilities.Local) { val irParent = conversionScope.parentFromStack() // NB: for implicit types it is possible that local class is already cached - val irClass = classifierStorage.getIrClass(regularClass)?.apply { this.parent = irParent } + val irClass = classifierStorage.getCachedIrLocalClass(regularClass)?.apply { this.parent = irParent } if (irClass != null) { conversionScope.withParent(irClass) { memberGenerator.convertClassContent(irClass, regularClass) @@ -200,7 +202,7 @@ class Fir2IrVisitor( } converter.processLocalClassAndNestedClasses(regularClass, irParent) } - val irClass = classifierStorage.getIrClass(regularClass)!! + val irClass = classifierStorage.getIrClass(regularClass) if (regularClass.isSealed) { irClass.sealedSubclasses = regularClass.getIrSymbolsForSealedSubclasses() } @@ -711,7 +713,7 @@ class Fir2IrVisitor( // We anyway can use 'else' branch as fallback, but // this is an additional check of FIR2IR invariants // (source classes should be already built when we analyze bodies) - classifierStorage.getIrClass(firClass)!!.symbol + classifierStorage.getIrClass(firClass).symbol } else { /* * The only case when we can refer to non-source this is resolution to companion object of parent diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/FirIrProvider.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/FirIrProvider.kt index a5634dda85f..67fc030b5a4 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/FirIrProvider.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/FirIrProvider.kt @@ -172,15 +172,14 @@ class FirIrProvider(val components: Fir2IrComponents) : IrProvider { } val firDeclaration = findDeclarationByHash(firCandidates, signature.id) ?: return null - val parent = parentClass ?: declarationStorage.getIrExternalPackageFragment(packageFqName, firDeclaration.moduleData) return when (kind) { SymbolKind.CLASS_SYMBOL -> { shouldNotBeCalled() } - SymbolKind.ENUM_ENTRY_SYMBOL -> classifierStorage.getOrCreateIrEnumEntry( - firDeclaration as FirEnumEntry, parent as IrClass - ) + SymbolKind.ENUM_ENTRY_SYMBOL -> { + shouldNotBeCalled() + } SymbolKind.CONSTRUCTOR_SYMBOL -> { shouldNotBeCalled() } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyClass.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyClass.kt index 3f608751922..971331e197c 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyClass.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyClass.kt @@ -181,7 +181,7 @@ class Fir2IrLazyClass( if (fir.classKind == ClassKind.ENUM_CLASS) { for (declaration in fir.declarations) { if (declaration is FirEnumEntry && shouldBuildStub(declaration)) { - result += classifierStorage.getOrCreateIrEnumEntry(declaration, this, origin) + result += classifierStorage.getIrEnumEntrySymbol(declaration).owner } } } diff --git a/compiler/testData/codegen/box/annotations/selfReferentialAnnotation.fir.ir.txt b/compiler/testData/codegen/box/annotations/selfReferentialAnnotation.fir.ir.txt index 383d6f1976a..238879d394f 100644 --- a/compiler/testData/codegen/box/annotations/selfReferentialAnnotation.fir.ir.txt +++ b/compiler/testData/codegen/box/annotations/selfReferentialAnnotation.fir.ir.txt @@ -60,10 +60,10 @@ FILE fqName: fileName:/selfReferentialAnnotation.kt receiver: GET_VAR ': .MyRequiresOptIn declared in .MyRequiresOptIn.' type=.MyRequiresOptIn origin=null CLASS ENUM_CLASS name:MyLevel modality:FINAL visibility:public superTypes:[kotlin.Enum<.MyRequiresOptIn.MyLevel>] $this: VALUE_PARAMETER INSTANCE_RECEIVER name: type:.MyRequiresOptIn.MyLevel - ENUM_ENTRY name:ERROR + ENUM_ENTRY name:WARNING init: EXPRESSION_BODY ENUM_CONSTRUCTOR_CALL 'private constructor () declared in .MyRequiresOptIn.MyLevel' - ENUM_ENTRY name:WARNING + ENUM_ENTRY name:ERROR init: EXPRESSION_BODY ENUM_CONSTRUCTOR_CALL 'private constructor () declared in .MyRequiresOptIn.MyLevel' CONSTRUCTOR visibility:private <> () returnType:.MyRequiresOptIn.MyLevel [primary] diff --git a/compiler/testData/codegen/box/annotations/selfReferentialAnnotation.kt b/compiler/testData/codegen/box/annotations/selfReferentialAnnotation.kt index 79c6324c908..76d1988b159 100644 --- a/compiler/testData/codegen/box/annotations/selfReferentialAnnotation.kt +++ b/compiler/testData/codegen/box/annotations/selfReferentialAnnotation.kt @@ -1,7 +1,6 @@ // FIR_DUMP // DUMP_IR // WITH_STDLIB -// IGNORE_BACKEND_K2: ANY annotation class Ann(@Ann(1) val e: Int)