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 c0f34af3a59..35a22d948d7 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 @@ -7,10 +7,12 @@ package org.jetbrains.kotlin.fir.backend import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.fir.containingClassLookupTag +import org.jetbrains.kotlin.fir.containingClassForLocalAttr import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.utils.* import org.jetbrains.kotlin.fir.expressions.FirAnonymousObjectExpression import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyClass +import org.jetbrains.kotlin.fir.resolve.getSymbolByLookupTag import org.jetbrains.kotlin.fir.resolve.providers.firProvider import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider import org.jetbrains.kotlin.fir.resolve.toSymbol @@ -203,22 +205,34 @@ class Fir2IrClassifierStorage( // This function is called when we refer local class earlier than we reach its declaration // This can happen e.g. when implicit return type has a local class constructor private fun createLocalIrClassOnTheFly(klass: FirClass): IrClass { - val result = when (klass) { - is FirAnonymousObject -> createIrAnonymousObject(klass, irParent = temporaryParent).apply { - converter.processAnonymousObjectOnTheFly(klass, this) + // finding the parent class that actually contains the [klass] in the tree - it is the root one that should be created on the fly + val classOrLocalParent = generateSequence(klass) { c -> + (c as? FirRegularClass)?.containingClassForLocalAttr?.let { + (firProvider.symbolProvider.getSymbolByLookupTag(it)?.fir as? FirClass)?.takeIf { + it.declarations.contains(c) + } + } + }.last() + val result = when (classOrLocalParent) { + is FirAnonymousObject -> createIrAnonymousObject(classOrLocalParent, irParent = temporaryParent).apply { + converter.processAnonymousObjectOnTheFly(classOrLocalParent, this) + } + is FirRegularClass -> { + converter.processLocalClassAndNestedClassesOnTheFly(classOrLocalParent, temporaryParent) } - is FirRegularClass -> converter.processLocalClassAndNestedClassesOnTheFly(klass, temporaryParent) } // Note: usually member creation and f/o binding is delayed till non-local classes are processed in Fir2IrConverter // If non-local classes are already created (this means we are in body translation) we do everything immediately // The last variant is possible for local variables like 'val a = object : Any() { ... }' if (processMembersOfClassesOnTheFlyImmediately) { - processMembersOfClassCreatedOnTheFly(klass, result) + processMembersOfClassCreatedOnTheFly(classOrLocalParent, result) converter.bindFakeOverridesInClass(result) } else { - localClassesCreatedOnTheFly[klass] = result + localClassesCreatedOnTheFly[classOrLocalParent] = result } - return result + return if (classOrLocalParent === klass) result + else (getCachedIrClass(klass) + ?: error("Assuming that all nested classes of ${classOrLocalParent.classId.asString()} should already be cached")) } // Note: this function is called exactly once, right after Fir2IrConverter finished f/o binding for regular classes