From 982ab8beac55b875c03257bd0306b29d38220e60 Mon Sep 17 00:00:00 2001 From: Ilya Chernikov Date: Wed, 3 Aug 2022 16:00:54 +0200 Subject: [PATCH] FIR2IR: fix processing of classes created on the fly finding local parent and create it on the fly, instead of the requested class. avoiding double processing of class members and properly handling "innerness" fixes localClassMetadata test problem with propLocal.<>.D --- .../fir/backend/Fir2IrClassifierStorage.kt | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 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 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