FIR2IR: split local class on-the-fly creation into two phases
This commit is contained in:
committed by
teamcityserver
parent
4a16027873
commit
3263d4d003
+32
-3
@@ -44,6 +44,10 @@ class Fir2IrClassifierStorage(
|
|||||||
|
|
||||||
private val classCache = mutableMapOf<FirRegularClass, IrClass>()
|
private val classCache = mutableMapOf<FirRegularClass, IrClass>()
|
||||||
|
|
||||||
|
private val localClassesCreatedOnTheFly = mutableMapOf<FirClass, IrClass>()
|
||||||
|
|
||||||
|
private var processMembersOfClassesOnTheFlyImmediately = false
|
||||||
|
|
||||||
private val typeAliasCache = mutableMapOf<FirTypeAlias, IrTypeAlias>()
|
private val typeAliasCache = mutableMapOf<FirTypeAlias, IrTypeAlias>()
|
||||||
|
|
||||||
private val typeParameterCache = mutableMapOf<FirTypeParameter, IrTypeParameter>()
|
private val typeParameterCache = mutableMapOf<FirTypeParameter, IrTypeParameter>()
|
||||||
@@ -168,16 +172,41 @@ class Fir2IrClassifierStorage(
|
|||||||
// This function is called when we refer local class earlier than we reach its declaration
|
// 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
|
// This can happen e.g. when implicit return type has a local class constructor
|
||||||
private fun createLocalIrClassOnTheFly(klass: FirClass): IrClass {
|
private fun createLocalIrClassOnTheFly(klass: FirClass): IrClass {
|
||||||
// NB: klass can be either FirRegularClass or FirAnonymousObject
|
|
||||||
val result = when (klass) {
|
val result = when (klass) {
|
||||||
is FirAnonymousObject -> createIrAnonymousObject(klass, irParent = temporaryParent).apply {
|
is FirAnonymousObject -> createIrAnonymousObject(klass, irParent = temporaryParent).apply {
|
||||||
converter.processAnonymousObjectMembers(klass, this)
|
converter.processAnonymousObjectOnTheFly(klass, this)
|
||||||
}
|
}
|
||||||
is FirRegularClass -> converter.processLocalClassAndNestedClasses(klass, 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)
|
||||||
|
converter.bindFakeOverridesInClass(result)
|
||||||
|
} else {
|
||||||
|
localClassesCreatedOnTheFly[klass] = result
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun processMembersOfClassesCreatedOnTheFly() {
|
||||||
|
processMembersOfClassesOnTheFlyImmediately = true
|
||||||
|
for ((klass, irClass) in localClassesCreatedOnTheFly) {
|
||||||
|
processMembersOfClassCreatedOnTheFly(klass, irClass)
|
||||||
|
}
|
||||||
|
// Note: it's better to bind everything AFTER members are built, in case local classes are dependent on each other
|
||||||
|
localClassesCreatedOnTheFly.values.forEach(converter::bindFakeOverridesInClass)
|
||||||
|
localClassesCreatedOnTheFly.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun processMembersOfClassCreatedOnTheFly(klass: FirClass, irClass: IrClass) {
|
||||||
|
when (klass) {
|
||||||
|
is FirRegularClass -> converter.processClassMembers(klass, irClass)
|
||||||
|
is FirAnonymousObject -> converter.processAnonymousObjectMembers(klass, irClass, processHeaders = false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun processClassHeader(regularClass: FirRegularClass, irClass: IrClass = getCachedIrClass(regularClass)!!): IrClass {
|
fun processClassHeader(regularClass: FirRegularClass, irClass: IrClass = getCachedIrClass(regularClass)!!): IrClass {
|
||||||
irClass.declareTypeParameters(regularClass)
|
irClass.declareTypeParameters(regularClass)
|
||||||
irClass.setThisReceiver(regularClass.typeParameters)
|
irClass.setThisReceiver(regularClass.typeParameters)
|
||||||
|
|||||||
@@ -52,6 +52,17 @@ class Fir2IrConverter(
|
|||||||
|
|
||||||
private val generatorExtensions = session.extensionService.declarationGenerators
|
private val generatorExtensions = session.extensionService.declarationGenerators
|
||||||
|
|
||||||
|
fun processLocalClassAndNestedClassesOnTheFly(regularClass: FirRegularClass, parent: IrDeclarationParent): IrClass {
|
||||||
|
val irClass = registerClassAndNestedClasses(regularClass, parent)
|
||||||
|
processClassAndNestedClassHeaders(regularClass)
|
||||||
|
return irClass
|
||||||
|
}
|
||||||
|
|
||||||
|
fun processAnonymousObjectOnTheFly(anonymousObject: FirAnonymousObject, irClass: IrClass) {
|
||||||
|
registerNestedClasses(anonymousObject, irClass)
|
||||||
|
processNestedClassHeaders(anonymousObject)
|
||||||
|
}
|
||||||
|
|
||||||
fun processLocalClassAndNestedClasses(regularClass: FirRegularClass, parent: IrDeclarationParent): IrClass {
|
fun processLocalClassAndNestedClasses(regularClass: FirRegularClass, parent: IrDeclarationParent): IrClass {
|
||||||
val irClass = registerClassAndNestedClasses(regularClass, parent)
|
val irClass = registerClassAndNestedClasses(regularClass, parent)
|
||||||
processClassAndNestedClassHeaders(regularClass)
|
processClassAndNestedClassHeaders(regularClass)
|
||||||
@@ -117,10 +128,13 @@ class Fir2IrConverter(
|
|||||||
|
|
||||||
fun processAnonymousObjectMembers(
|
fun processAnonymousObjectMembers(
|
||||||
anonymousObject: FirAnonymousObject,
|
anonymousObject: FirAnonymousObject,
|
||||||
irClass: IrClass = classifierStorage.getCachedIrClass(anonymousObject)!!
|
irClass: IrClass,
|
||||||
|
processHeaders: Boolean
|
||||||
): IrClass {
|
): IrClass {
|
||||||
registerNestedClasses(anonymousObject, irClass)
|
if (processHeaders) {
|
||||||
processNestedClassHeaders(anonymousObject)
|
registerNestedClasses(anonymousObject, irClass)
|
||||||
|
processNestedClassHeaders(anonymousObject)
|
||||||
|
}
|
||||||
anonymousObject.primaryConstructorIfAny(session)?.let {
|
anonymousObject.primaryConstructorIfAny(session)?.let {
|
||||||
irClass.declarations += declarationStorage.createIrConstructor(
|
irClass.declarations += declarationStorage.createIrConstructor(
|
||||||
it.fir, irClass, isLocal = true
|
it.fir, irClass, isLocal = true
|
||||||
@@ -388,6 +402,7 @@ class Fir2IrConverter(
|
|||||||
for (firFile in allFirFiles) {
|
for (firFile in allFirFiles) {
|
||||||
converter.bindFakeOverridesInFile(firFile)
|
converter.bindFakeOverridesInFile(firFile)
|
||||||
}
|
}
|
||||||
|
classifierStorage.processMembersOfClassesCreatedOnTheFly()
|
||||||
|
|
||||||
for (firFile in allFirFiles) {
|
for (firFile in allFirFiles) {
|
||||||
firFile.accept(fir2irVisitor, null)
|
firFile.accept(fir2irVisitor, null)
|
||||||
|
|||||||
+1
-5
@@ -1167,11 +1167,7 @@ class Fir2IrDeclarationStorage(
|
|||||||
) as IrFunctionSymbol
|
) as IrFunctionSymbol
|
||||||
if (unmatchedReceiver && dispatchReceiverLookupTag is ConeClassLookupTagWithFixedSymbol) {
|
if (unmatchedReceiver && dispatchReceiverLookupTag is ConeClassLookupTagWithFixedSymbol) {
|
||||||
val originalFunction = originalSymbol.owner as IrSimpleFunction
|
val originalFunction = originalSymbol.owner as IrSimpleFunction
|
||||||
dispatchReceiverLookupTag.findIrFakeOverride(
|
dispatchReceiverLookupTag.findIrFakeOverride(fir.name, originalFunction) as IrFunctionSymbol
|
||||||
fir.name, originalFunction
|
|
||||||
) as? IrFunctionSymbol
|
|
||||||
// Fallback for simple synthetic property
|
|
||||||
?: originalSymbol
|
|
||||||
} else {
|
} else {
|
||||||
originalSymbol
|
originalSymbol
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ class Fir2IrVisitor(
|
|||||||
declarationStorage.enterScope(irEnumEntry)
|
declarationStorage.enterScope(irEnumEntry)
|
||||||
classifierStorage.putEnumEntryClassInScope(enumEntry, correspondingClass)
|
classifierStorage.putEnumEntryClassInScope(enumEntry, correspondingClass)
|
||||||
val anonymousObject = (enumEntry.initializer as FirAnonymousObjectExpression).anonymousObject
|
val anonymousObject = (enumEntry.initializer as FirAnonymousObjectExpression).anonymousObject
|
||||||
converter.processAnonymousObjectMembers(anonymousObject, correspondingClass)
|
converter.processAnonymousObjectMembers(anonymousObject, correspondingClass, processHeaders = true)
|
||||||
conversionScope.withParent(correspondingClass) {
|
conversionScope.withParent(correspondingClass) {
|
||||||
conversionScope.withContainingFirClass(anonymousObject) {
|
conversionScope.withContainingFirClass(anonymousObject) {
|
||||||
memberGenerator.convertClassContent(correspondingClass, anonymousObject)
|
memberGenerator.convertClassContent(correspondingClass, anonymousObject)
|
||||||
@@ -177,8 +177,8 @@ class Fir2IrVisitor(
|
|||||||
val irParent = conversionScope.parentFromStack()
|
val irParent = conversionScope.parentFromStack()
|
||||||
// NB: for implicit types it is possible that anonymous object is already cached
|
// NB: for implicit types it is possible that anonymous object is already cached
|
||||||
val irAnonymousObject = classifierStorage.getCachedIrClass(anonymousObject)?.apply { this.parent = irParent }
|
val irAnonymousObject = classifierStorage.getCachedIrClass(anonymousObject)?.apply { this.parent = irParent }
|
||||||
?: classifierStorage.createIrAnonymousObject(anonymousObject, irParent = irParent).also {
|
?: classifierStorage.createIrAnonymousObject(anonymousObject, irParent = irParent).also { irClass ->
|
||||||
converter.processAnonymousObjectMembers(anonymousObject, it)
|
converter.processAnonymousObjectMembers(anonymousObject, irClass, processHeaders = true)
|
||||||
}
|
}
|
||||||
conversionScope.withParent(irAnonymousObject) {
|
conversionScope.withParent(irAnonymousObject) {
|
||||||
conversionScope.withContainingFirClass(anonymousObject) {
|
conversionScope.withContainingFirClass(anonymousObject) {
|
||||||
|
|||||||
Reference in New Issue
Block a user