FIR2IR: make handling of FirRegularClass & FirAnonymousObject more consistent
#KT-57221 Fixed
This commit is contained in:
committed by
Space Team
parent
51cd1b2d6f
commit
e1c2dc06f1
+23
-32
@@ -88,6 +88,7 @@ class Fir2IrClassifierStorage(
|
||||
}
|
||||
}
|
||||
|
||||
// Note: declareTypeParameters should be called before!
|
||||
private fun IrClass.setThisReceiver(typeParameters: List<FirTypeParameterRef>) {
|
||||
symbolTable.enterScope(this)
|
||||
val typeArguments = typeParameters.map {
|
||||
@@ -129,9 +130,9 @@ class Fir2IrClassifierStorage(
|
||||
}
|
||||
|
||||
private fun IrClass.declareTypeParameters(klass: FirClass) {
|
||||
preCacheTypeParameters(klass, symbol)
|
||||
setTypeParameters(klass)
|
||||
if (klass is FirRegularClass) {
|
||||
preCacheTypeParameters(klass, symbol)
|
||||
setTypeParameters(klass)
|
||||
val fieldsForContextReceiversOfCurrentClass = createContextReceiverFields(klass)
|
||||
if (fieldsForContextReceiversOfCurrentClass.isNotEmpty()) {
|
||||
declarations.addAll(fieldsForContextReceiversOfCurrentClass)
|
||||
@@ -175,12 +176,6 @@ class Fir2IrClassifierStorage(
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrClass.declareSupertypesAndTypeParameters(klass: FirClass): IrClass {
|
||||
declareTypeParameters(klass)
|
||||
declareSupertypes(klass)
|
||||
return this
|
||||
}
|
||||
|
||||
fun getCachedIrClass(klass: FirClass): IrClass? {
|
||||
return if (klass is FirAnonymousObject || klass is FirRegularClass && klass.visibility == Visibilities.Local) {
|
||||
localStorage[klass]
|
||||
@@ -242,14 +237,7 @@ class Fir2IrClassifierStorage(
|
||||
}
|
||||
}
|
||||
}.last()
|
||||
val result = when (classOrLocalParent) {
|
||||
is FirAnonymousObject -> createIrAnonymousObject(classOrLocalParent, irParent = temporaryParent).apply {
|
||||
converter.processAnonymousObjectOnTheFly(classOrLocalParent, this)
|
||||
}
|
||||
is FirRegularClass -> {
|
||||
converter.processLocalClassAndNestedClassesOnTheFly(classOrLocalParent, temporaryParent)
|
||||
}
|
||||
}
|
||||
val result = converter.processLocalClassAndNestedClassesOnTheFly(classOrLocalParent, 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() { ... }'
|
||||
@@ -279,16 +267,18 @@ class Fir2IrClassifierStorage(
|
||||
|
||||
private fun processMembersOfClassCreatedOnTheFly(klass: FirClass, irClass: IrClass) {
|
||||
when (klass) {
|
||||
is FirRegularClass -> converter.processClassMembers(klass, irClass)
|
||||
is FirRegularClass -> converter.processRegularClassMembers(klass, irClass)
|
||||
is FirAnonymousObject -> converter.processAnonymousObjectMembers(klass, irClass, processHeaders = false)
|
||||
}
|
||||
}
|
||||
|
||||
fun processClassHeader(regularClass: FirRegularClass, irClass: IrClass = getCachedIrClass(regularClass)!!): IrClass {
|
||||
irClass.declareTypeParameters(regularClass)
|
||||
irClass.setThisReceiver(regularClass.typeParameters)
|
||||
irClass.declareSupertypes(regularClass)
|
||||
irClass.declareValueClassRepresentation(regularClass)
|
||||
fun processClassHeader(klass: FirClass, irClass: IrClass = getCachedIrClass(klass)!!): IrClass {
|
||||
irClass.declareTypeParameters(klass)
|
||||
irClass.setThisReceiver(klass.typeParameters)
|
||||
irClass.declareSupertypes(klass)
|
||||
if (klass is FirRegularClass) {
|
||||
irClass.declareValueClassRepresentation(klass)
|
||||
}
|
||||
return irClass
|
||||
}
|
||||
|
||||
@@ -378,7 +368,7 @@ class Fir2IrClassifierStorage(
|
||||
return irClass
|
||||
}
|
||||
|
||||
fun createIrAnonymousObject(
|
||||
fun registerIrAnonymousObject(
|
||||
anonymousObject: FirAnonymousObject,
|
||||
visibility: Visibility = Visibilities.Local,
|
||||
name: Name = Name.special("<no name provided>"),
|
||||
@@ -386,7 +376,7 @@ class Fir2IrClassifierStorage(
|
||||
): IrClass {
|
||||
val origin = IrDeclarationOrigin.DEFINED
|
||||
val modality = Modality.FINAL
|
||||
val result = anonymousObject.convertWithOffsets { startOffset, endOffset ->
|
||||
val irAnonymousObject = anonymousObject.convertWithOffsets { startOffset, endOffset ->
|
||||
irFactory.createClass(
|
||||
startOffset, endOffset, origin, IrClassSymbolImpl(), name,
|
||||
// NB: for unknown reason, IR uses 'CLASS' kind for simple anonymous objects
|
||||
@@ -394,19 +384,20 @@ class Fir2IrClassifierStorage(
|
||||
components.visibilityConverter.convertToDescriptorVisibility(visibility), modality
|
||||
).apply {
|
||||
metadata = FirMetadataSource.Class(anonymousObject)
|
||||
setThisReceiver(anonymousObject.typeParameters)
|
||||
if (irParent != null) {
|
||||
this.parent = irParent
|
||||
}
|
||||
}
|
||||
}.declareSupertypesAndTypeParameters(anonymousObject)
|
||||
localStorage[anonymousObject] = result
|
||||
return result
|
||||
}
|
||||
if (irParent != null) {
|
||||
irAnonymousObject.parent = irParent
|
||||
}
|
||||
localStorage[anonymousObject] = irAnonymousObject
|
||||
return irAnonymousObject
|
||||
}
|
||||
|
||||
private fun getIrAnonymousObjectForEnumEntry(anonymousObject: FirAnonymousObject, name: Name, irParent: IrClass?): IrClass {
|
||||
localStorage[anonymousObject]?.let { return it }
|
||||
return createIrAnonymousObject(anonymousObject, Visibilities.Private, name, irParent)
|
||||
val irAnonymousObject = registerIrAnonymousObject(anonymousObject, Visibilities.Private, name, irParent)
|
||||
processClassHeader(anonymousObject, irAnonymousObject)
|
||||
return irAnonymousObject
|
||||
}
|
||||
|
||||
private fun createIrTypeParameterWithoutBounds(
|
||||
|
||||
@@ -5,13 +5,11 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.backend
|
||||
|
||||
import org.jetbrains.kotlin.KtFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.KtPsiSourceFileLinesMapping
|
||||
import org.jetbrains.kotlin.KtSourceFileLinesMappingFromLineStartOffsets
|
||||
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
|
||||
import org.jetbrains.kotlin.builtins.DefaultBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.config.AnalysisFlags
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
@@ -118,21 +116,19 @@ class Fir2IrConverter(
|
||||
}
|
||||
}
|
||||
|
||||
fun processLocalClassAndNestedClassesOnTheFly(regularClass: FirRegularClass, parent: IrDeclarationParent): IrClass {
|
||||
val irClass = registerClassAndNestedClasses(regularClass, parent)
|
||||
processClassAndNestedClassHeaders(regularClass)
|
||||
fun processLocalClassAndNestedClassesOnTheFly(klass: FirClass, parent: IrDeclarationParent): IrClass {
|
||||
val irClass = registerClassAndNestedClasses(klass, parent)
|
||||
processClassAndNestedClassHeaders(klass)
|
||||
return irClass
|
||||
}
|
||||
|
||||
fun processAnonymousObjectOnTheFly(anonymousObject: FirAnonymousObject, irClass: IrClass) {
|
||||
registerNestedClasses(anonymousObject, irClass)
|
||||
processNestedClassHeaders(anonymousObject)
|
||||
}
|
||||
|
||||
fun processLocalClassAndNestedClasses(regularClass: FirRegularClass, parent: IrDeclarationParent): IrClass {
|
||||
val irClass = registerClassAndNestedClasses(regularClass, parent)
|
||||
processClassAndNestedClassHeaders(regularClass)
|
||||
processClassMembers(regularClass, irClass)
|
||||
fun processLocalClassAndNestedClasses(klass: FirClass, parent: IrDeclarationParent): IrClass {
|
||||
val irClass = registerClassAndNestedClasses(klass, parent)
|
||||
processClassAndNestedClassHeaders(klass)
|
||||
when (klass) {
|
||||
is FirRegularClass -> processRegularClassMembers(klass, irClass)
|
||||
is FirAnonymousObject -> processAnonymousObjectMembers(klass, irClass, processHeaders = false)
|
||||
}
|
||||
bindFakeOverridesInClass(irClass)
|
||||
return irClass
|
||||
}
|
||||
@@ -187,6 +183,7 @@ class Fir2IrConverter(
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: unite with/extract common part from processRegularClassMembers
|
||||
fun processAnonymousObjectMembers(
|
||||
anonymousObject: FirAnonymousObject,
|
||||
irClass: IrClass,
|
||||
@@ -211,12 +208,11 @@ class Fir2IrConverter(
|
||||
with(fakeOverrideGenerator) {
|
||||
irClass.addFakeOverrides(anonymousObject, realDeclarations)
|
||||
}
|
||||
bindFakeOverridesInClass(irClass)
|
||||
|
||||
return irClass
|
||||
}
|
||||
|
||||
internal fun processClassMembers(
|
||||
internal fun processRegularClassMembers(
|
||||
regularClass: FirRegularClass,
|
||||
irClass: IrClass = classifierStorage.getCachedIrClass(regularClass)!!
|
||||
): IrClass {
|
||||
@@ -298,14 +294,17 @@ class Fir2IrConverter(
|
||||
return declarations.sortedBy { it !is FirField && it.isSynthetic }
|
||||
}
|
||||
|
||||
private fun registerClassAndNestedClasses(regularClass: FirRegularClass, parent: IrDeclarationParent): IrClass {
|
||||
private fun registerClassAndNestedClasses(klass: FirClass, parent: IrDeclarationParent): IrClass {
|
||||
// Local classes might be referenced before they declared (see usages of Fir2IrClassifierStorage.createLocalIrClassOnTheFly)
|
||||
// So, we only need to set its parent properly
|
||||
val irClass =
|
||||
classifierStorage.getCachedIrClass(regularClass)?.apply {
|
||||
classifierStorage.getCachedIrClass(klass)?.apply {
|
||||
this.parent = parent
|
||||
} ?: classifierStorage.registerIrClass(regularClass, parent)
|
||||
registerNestedClasses(regularClass, irClass)
|
||||
} ?: when (klass) {
|
||||
is FirRegularClass -> classifierStorage.registerIrClass(klass, parent)
|
||||
is FirAnonymousObject -> classifierStorage.registerIrAnonymousObject(klass, irParent = parent)
|
||||
}
|
||||
registerNestedClasses(klass, irClass)
|
||||
return irClass
|
||||
}
|
||||
|
||||
@@ -324,9 +323,9 @@ class Fir2IrConverter(
|
||||
}
|
||||
}
|
||||
|
||||
private fun processClassAndNestedClassHeaders(regularClass: FirRegularClass) {
|
||||
classifierStorage.processClassHeader(regularClass)
|
||||
processNestedClassHeaders(regularClass)
|
||||
private fun processClassAndNestedClassHeaders(klass: FirClass) {
|
||||
classifierStorage.processClassHeader(klass)
|
||||
processNestedClassHeaders(klass)
|
||||
}
|
||||
|
||||
private fun processNestedClassHeaders(klass: FirClass) {
|
||||
@@ -353,7 +352,7 @@ class Fir2IrConverter(
|
||||
(containingClass !is FirRegularClass || containingClass.isLocal)
|
||||
return when (declaration) {
|
||||
is FirRegularClass -> {
|
||||
processClassMembers(declaration)
|
||||
processRegularClassMembers(declaration)
|
||||
}
|
||||
is FirScript -> {
|
||||
assert(parent is IrFile)
|
||||
|
||||
@@ -124,6 +124,7 @@ class Fir2IrVisitor(
|
||||
classifierStorage.putEnumEntryClassInScope(enumEntry, correspondingClass)
|
||||
val anonymousObject = (enumEntry.initializer as FirAnonymousObjectExpression).anonymousObject
|
||||
converter.processAnonymousObjectMembers(anonymousObject, correspondingClass, processHeaders = true)
|
||||
converter.bindFakeOverridesInClass(correspondingClass)
|
||||
conversionScope.withParent(correspondingClass) {
|
||||
conversionScope.withContainingFirClass(anonymousObject) {
|
||||
memberGenerator.convertClassContent(correspondingClass, anonymousObject)
|
||||
@@ -223,9 +224,8 @@ class Fir2IrVisitor(
|
||||
val irParent = conversionScope.parentFromStack()
|
||||
// NB: for implicit types it is possible that anonymous object is already cached
|
||||
val irAnonymousObject = classifierStorage.getCachedIrClass(anonymousObject)?.apply { this.parent = irParent }
|
||||
?: classifierStorage.createIrAnonymousObject(anonymousObject, irParent = irParent).also { irClass ->
|
||||
converter.processAnonymousObjectMembers(anonymousObject, irClass, processHeaders = true)
|
||||
}
|
||||
?: converter.processLocalClassAndNestedClasses(anonymousObject, irParent)
|
||||
|
||||
conversionScope.withParent(irAnonymousObject) {
|
||||
conversionScope.withContainingFirClass(anonymousObject) {
|
||||
memberGenerator.convertClassContent(irAnonymousObject, anonymousObject)
|
||||
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
FILE fqName:<root> fileName:/AnonymousAsReturnOfGenericFunction.kt
|
||||
CLASS INTERFACE name:NestedGroupFragment modality:ABSTRACT visibility:public superTypes:[kotlin.Any]
|
||||
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.NestedGroupFragment
|
||||
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
|
||||
overridden:
|
||||
public open fun equals (other: kotlin.Any?): kotlin.Boolean [operator] declared in kotlin.Any
|
||||
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
|
||||
VALUE_PARAMETER name:other index:0 type:kotlin.Any?
|
||||
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override]
|
||||
overridden:
|
||||
public open fun hashCode (): kotlin.Int declared in kotlin.Any
|
||||
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
|
||||
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override]
|
||||
overridden:
|
||||
public open fun toString (): kotlin.String declared in kotlin.Any
|
||||
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
|
||||
FUN name:addMavenOptionsGroupFragment visibility:private modality:FINAL <> () returnType:<root>.addOptionsGroup.<no name provided><kotlin.Int>
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='private final fun addMavenOptionsGroupFragment (): <root>.addOptionsGroup.<no name provided><kotlin.Int> declared in <root>'
|
||||
CALL 'private final fun addOptionsGroup <S> (): <root>.addOptionsGroup.<no name provided><S of <root>.addOptionsGroup> declared in <root>' type=<root>.addOptionsGroup.<no name provided><kotlin.Int> origin=null
|
||||
<S>: kotlin.Int
|
||||
FUN name:addOptionsGroup visibility:private modality:FINAL <S> () returnType:<root>.addOptionsGroup.<no name provided><S of <root>.addOptionsGroup>
|
||||
TYPE_PARAMETER name:S index:0 variance: superTypes:[kotlin.Any?] reified:false
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='private final fun addOptionsGroup <S> (): <root>.addOptionsGroup.<no name provided><S of <root>.addOptionsGroup> declared in <root>'
|
||||
BLOCK type=<root>.addOptionsGroup.<no name provided><S of <root>.addOptionsGroup> origin=OBJECT_LITERAL
|
||||
CLASS CLASS name:<no name provided> modality:FINAL visibility:local superTypes:[<root>.NestedGroupFragment]
|
||||
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.addOptionsGroup.<no name provided><S of <root>.addOptionsGroup>
|
||||
CONSTRUCTOR visibility:private <> () returnType:<root>.addOptionsGroup.<no name provided><S of <root>.addOptionsGroup> [primary]
|
||||
BLOCK_BODY
|
||||
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () [primary] declared in kotlin.Any'
|
||||
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:<no name provided> modality:FINAL visibility:local superTypes:[<root>.NestedGroupFragment]'
|
||||
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
|
||||
overridden:
|
||||
public open fun equals (other: kotlin.Any?): kotlin.Boolean [fake_override,operator] declared in <root>.NestedGroupFragment
|
||||
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
|
||||
VALUE_PARAMETER name:other index:0 type:kotlin.Any?
|
||||
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override]
|
||||
overridden:
|
||||
public open fun hashCode (): kotlin.Int [fake_override] declared in <root>.NestedGroupFragment
|
||||
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
|
||||
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override]
|
||||
overridden:
|
||||
public open fun toString (): kotlin.String [fake_override] declared in <root>.NestedGroupFragment
|
||||
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
|
||||
CONSTRUCTOR_CALL 'private constructor <init> () [primary] declared in <root>.addOptionsGroup.<no name provided>' type=<root>.addOptionsGroup.<no name provided><S of <root>.addOptionsGroup> origin=OBJECT_LITERAL
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
interface NestedGroupFragment {
|
||||
|
||||
}
|
||||
|
||||
private fun addMavenOptionsGroupFragment(): <no name provided><Int> {
|
||||
return addOptionsGroup<Int>()
|
||||
}
|
||||
|
||||
private fun <S : Any?> addOptionsGroup(): <no name provided><S> {
|
||||
return { // BLOCK
|
||||
local class <no name provided> : NestedGroupFragment {
|
||||
private constructor() /* primary */ {
|
||||
super/*Any*/()
|
||||
/* <init>() */
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
<no name provided>()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user