[FIR2IR] Extract separate classifier storage from declaration storage

This commit is contained in:
Mikhail Glukhikh
2020-03-13 09:49:12 +03:00
parent 95b77f6386
commit 175145ce4e
6 changed files with 455 additions and 390 deletions

View File

@@ -21,7 +21,6 @@ import org.jetbrains.kotlin.fir.references.FirThisReference
import org.jetbrains.kotlin.fir.references.impl.FirPropertyFromParameterResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.calls.SyntheticPropertySymbol
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.AccessorSymbol
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
@@ -70,28 +69,32 @@ class ConversionTypeContext internal constructor(
}
}
fun FirClassifierSymbol<*>.toIrSymbol(
fun FirClassifierSymbol<*>.toSymbol(
session: FirSession,
declarationStorage: Fir2IrDeclarationStorage,
classifierStorage: Fir2IrClassifierStorage,
typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT
): IrClassifierSymbol {
return when (this) {
is FirTypeParameterSymbol -> {
declarationStorage.getIrTypeParameterSymbol(this, typeContext)
classifierStorage.getIrTypeParameterSymbol(this, typeContext)
}
is FirTypeAliasSymbol -> {
val typeAlias = fir
val coneClassLikeType = (typeAlias.expandedTypeRef as FirResolvedTypeRef).type as ConeClassLikeType
coneClassLikeType.lookupTag.toSymbol(session)!!.toIrSymbol(session, declarationStorage)
coneClassLikeType.lookupTag.toSymbol(session)!!.toSymbol(session, classifierStorage)
}
is FirClassSymbol -> {
declarationStorage.getIrClassSymbol(this)
classifierStorage.getIrClassSymbol(this)
}
else -> throw AssertionError("Should not be here: $this")
}
}
fun FirReference.toSymbol(declarationStorage: Fir2IrDeclarationStorage): IrSymbol? {
fun FirReference.toSymbol(
session: FirSession,
classifierStorage: Fir2IrClassifierStorage,
declarationStorage: Fir2IrDeclarationStorage
): IrSymbol? {
return when (this) {
is FirResolvedNamedReference -> {
when (val resolvedSymbol = resolvedSymbol) {
@@ -100,15 +103,18 @@ fun FirReference.toSymbol(declarationStorage: Fir2IrDeclarationStorage): IrSymbo
resolvedSymbol.overriddenSymbol?.takeIf { it.callableId == resolvedSymbol.callableId } ?: resolvedSymbol
originalCallableSymbol.toSymbol(declarationStorage)
}
is FirClassifierSymbol<*> -> {
resolvedSymbol.toSymbol(session, classifierStorage)
}
else -> {
resolvedSymbol.toSymbol(declarationStorage)
throw AssertionError("Unknown symbol: $resolvedSymbol")
}
}
}
is FirThisReference -> {
when (val boundSymbol = boundSymbol?.toSymbol(declarationStorage)) {
is IrClassSymbol -> boundSymbol.owner.thisReceiver?.symbol
is IrFunctionSymbol -> boundSymbol.owner.extensionReceiverParameter?.symbol
when (val boundSymbol = boundSymbol) {
is FirClassSymbol<*> -> classifierStorage.getIrClassSymbol(boundSymbol).owner.thisReceiver?.symbol
is FirFunctionSymbol -> declarationStorage.getIrFunctionSymbol(boundSymbol).owner.extensionReceiverParameter?.symbol
else -> null
}
}
@@ -116,10 +122,11 @@ fun FirReference.toSymbol(declarationStorage: Fir2IrDeclarationStorage): IrSymbo
}
}
private fun AbstractFirBasedSymbol<*>.toSymbol(declarationStorage: Fir2IrDeclarationStorage): IrSymbol? = when (this) {
is FirClassSymbol -> declarationStorage.getIrClassSymbol(this)
private fun FirCallableSymbol<*>.toSymbol(declarationStorage: Fir2IrDeclarationStorage): IrSymbol? = when (this) {
is FirFunctionSymbol<*> -> declarationStorage.getIrFunctionSymbol(this)
is FirPropertySymbol -> if (fir.isLocal) declarationStorage.getIrValueSymbol(this) else declarationStorage.getIrPropertyOrFieldSymbol(this)
is FirPropertySymbol -> {
if (fir.isLocal) declarationStorage.getIrValueSymbol(this) else declarationStorage.getIrPropertyOrFieldSymbol(this)
}
is FirFieldSymbol -> declarationStorage.getIrPropertyOrFieldSymbol(this)
is FirBackingFieldSymbol -> declarationStorage.getIrBackingFieldSymbol(this)
is FirDelegateFieldSymbol<*> -> declarationStorage.getIrBackingFieldSymbol(this)

View File

@@ -0,0 +1,364 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.backend
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.resolve.firProvider
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrEnumEntryImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrTypeParameterImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
import org.jetbrains.kotlin.ir.descriptors.*
import org.jetbrains.kotlin.ir.expressions.impl.IrEnumConstructorCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.util.constructors
import org.jetbrains.kotlin.name.Name
class Fir2IrClassifierStorage(
session: FirSession,
private val irSymbolTable: SymbolTable
) {
private val firProvider = session.firProvider
private val classCache = mutableMapOf<FirRegularClass, IrClass>()
private val typeParameterCache = mutableMapOf<FirTypeParameter, IrTypeParameter>()
private val typeParameterCacheForSetter = mutableMapOf<FirTypeParameter, IrTypeParameter>()
private val enumEntryCache = mutableMapOf<FirEnumEntry, IrEnumEntry>()
private val localStorage = Fir2IrLocalStorage()
lateinit var typeConverter: Fir2IrTypeConverter
lateinit var declarationStorage: Fir2IrDeclarationStorage
private fun FirTypeRef.toIrType(typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT): IrType =
with(typeConverter) { toIrType(typeContext) }
internal fun IrDeclaration.declareThisReceiverParameter(
parent: IrDeclarationParent,
thisType: IrType,
thisOrigin: IrDeclarationOrigin,
startOffset: Int = this.startOffset,
endOffset: Int = this.endOffset
): IrValueParameter {
val receiverDescriptor = WrappedReceiverParameterDescriptor()
return irSymbolTable.declareValueParameter(
startOffset, endOffset, thisOrigin, receiverDescriptor, thisType
) { symbol ->
IrValueParameterImpl(
startOffset, endOffset, thisOrigin, symbol,
Name.special("<this>"), -1, thisType,
varargElementType = null, isCrossinline = false, isNoinline = false
).apply {
this.parent = parent
receiverDescriptor.bind(this)
}
}
}
private fun IrClass.setThisReceiver() {
irSymbolTable.enterScope(descriptor)
val typeArguments = this.typeParameters.map {
IrSimpleTypeImpl(it.symbol, false, emptyList(), emptyList())
}
thisReceiver = declareThisReceiverParameter(
parent = this,
thisType = IrSimpleTypeImpl(symbol, false, typeArguments, emptyList()),
thisOrigin = IrDeclarationOrigin.INSTANCE_RECEIVER
)
irSymbolTable.leaveScope(descriptor)
}
internal fun preCacheTypeParameters(owner: FirTypeParametersOwner) {
owner.typeParameters.mapIndexed { index, typeParameter ->
getIrTypeParameter(typeParameter, index)
if (owner is FirProperty && owner.isVar) {
getIrTypeParameter(typeParameter, index, ConversionTypeContext.DEFAULT.inSetter())
}
}
}
internal fun IrTypeParametersContainer.setTypeParameters(
owner: FirTypeParametersOwner,
typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT
) {
typeParameters = owner.typeParameters.mapIndexed { index, typeParameter ->
getIrTypeParameter(typeParameter, index, typeContext).apply { parent = this@setTypeParameters }
}
}
private fun IrClass.declareSupertypesAndTypeParameters(klass: FirClass<*>): IrClass {
if (klass is FirRegularClass) {
setTypeParameters(klass)
}
superTypes = klass.superTypeRefs.map { superTypeRef -> superTypeRef.toIrType() }
return this
}
fun getCachedIrClass(klass: FirClass<*>): IrClass? {
return if (klass is FirAnonymousObject || klass is FirRegularClass && klass.visibility == Visibilities.LOCAL) {
localStorage.getLocalClass(klass)
} else {
classCache[klass]
}
}
private fun FirRegularClass.enumClassModality(): Modality {
return when {
declarations.any { it is FirCallableMemberDeclaration<*> && it.modality == Modality.ABSTRACT } -> {
Modality.ABSTRACT
}
declarations.any { it is FirEnumEntry && it.initializer != null } -> {
Modality.OPEN
}
else -> {
Modality.FINAL
}
}
}
internal fun createIrClass(klass: FirClass<*>, parent: IrDeclarationParent? = null): IrClass {
// NB: klass can be either FirRegularClass or FirAnonymousObject
if (klass is FirAnonymousObject) {
return createIrAnonymousObject(klass, irParent = parent)
}
val regularClass = klass as FirRegularClass
val origin =
if (firProvider.getFirClassifierContainerFileIfAny(klass.symbol) != null) IrDeclarationOrigin.DEFINED
else IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB
val irClass = registerIrClass(regularClass, parent, origin)
processClassHeader(regularClass, irClass)
return irClass
}
fun processClassHeader(regularClass: FirRegularClass, irClass: IrClass = getCachedIrClass(regularClass)!!): IrClass {
irClass.declareSupertypesAndTypeParameters(regularClass)
irClass.setThisReceiver()
return irClass
}
fun registerIrClass(
regularClass: FirRegularClass,
parent: IrDeclarationParent? = null,
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED
): IrClass {
val descriptor = WrappedClassDescriptor()
val visibility = regularClass.visibility
val modality = if (regularClass.classKind == ClassKind.ENUM_CLASS) {
regularClass.enumClassModality()
} else {
regularClass.modality ?: Modality.FINAL
}
val irClass = regularClass.convertWithOffsets { startOffset, endOffset ->
irSymbolTable.declareClass(startOffset, endOffset, origin, descriptor, modality, visibility) { symbol ->
IrClassImpl(
startOffset,
endOffset,
origin,
symbol,
regularClass.name,
regularClass.classKind,
visibility,
modality,
isCompanion = regularClass.isCompanion,
isInner = regularClass.isInner,
isData = regularClass.isData,
isExternal = regularClass.isExternal,
isInline = regularClass.isInline,
isExpect = regularClass.isExpect,
isFun = false // TODO FirRegularClass.isFun
).apply {
descriptor.bind(this)
}
}
}
if (parent != null) {
irClass.parent = parent
}
if (regularClass.visibility == Visibilities.LOCAL) {
localStorage.putLocalClass(regularClass, irClass)
} else {
classCache[regularClass] = irClass
}
return irClass
}
fun createIrAnonymousObject(
anonymousObject: FirAnonymousObject,
visibility: Visibility = Visibilities.LOCAL,
name: Name = Name.special("<no name provided>"),
irParent: IrDeclarationParent? = null
): IrClass {
val descriptor = WrappedClassDescriptor()
val origin = IrDeclarationOrigin.DEFINED
val modality = Modality.FINAL
val result = anonymousObject.convertWithOffsets { startOffset, endOffset ->
irSymbolTable.declareClass(startOffset, endOffset, origin, descriptor, modality, visibility) { symbol ->
IrClassImpl(
startOffset, endOffset, origin, symbol, name,
// NB: for unknown reason, IR uses 'CLASS' kind for simple anonymous objects
anonymousObject.classKind.takeIf { it == ClassKind.ENUM_ENTRY } ?: ClassKind.CLASS,
visibility, modality,
isCompanion = false, isInner = false, isData = false,
isExternal = false, isInline = false, isExpect = false, isFun = false
).apply {
descriptor.bind(this)
setThisReceiver()
if (irParent != null) {
this.parent = irParent
}
}
}
}.declareSupertypesAndTypeParameters(anonymousObject)
localStorage.putLocalClass(anonymousObject, result)
return result
}
private fun getIrAnonymousObjectForEnumEntry(anonymousObject: FirAnonymousObject, name: Name, irParent: IrClass?): IrClass {
localStorage.getLocalClass(anonymousObject)?.let { return it }
return createIrAnonymousObject(anonymousObject, Visibilities.PRIVATE, name, irParent)
}
private fun getIrTypeParameter(
typeParameter: FirTypeParameter,
index: Int = -1,
typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT
): IrTypeParameter {
// Here transformation is a bit difficult because one FIR property type parameter
// can be transformed to two different type parameters: one for getter and another one for setter
val simpleCachedParameter = typeParameterCache[typeParameter]
if (simpleCachedParameter != null) {
if (typeContext.origin != ConversionTypeOrigin.SETTER) {
return simpleCachedParameter
}
if (index < 0) {
val parent = simpleCachedParameter.parent
if (parent !is IrSimpleFunction || parent.returnType == typeConverter.unitType) {
return simpleCachedParameter
}
}
}
if (typeContext.origin == ConversionTypeOrigin.SETTER) {
typeParameterCacheForSetter[typeParameter]?.let { return it }
}
return typeParameter.run {
// Yet I don't want to enable this requirement because it breaks some tests
// However, if we get here it *should* mean that type parameter index is given explicitly
// At this moment (20.02.2020) this requirement breaks 11/355 Fir2IrText tests
// require(index != -1)
val descriptor = WrappedTypeParameterDescriptor()
val origin = IrDeclarationOrigin.DEFINED
val irTypeParameter =
convertWithOffsets { startOffset, endOffset ->
irSymbolTable.declareGlobalTypeParameter(startOffset, endOffset, origin, descriptor) { symbol ->
IrTypeParameterImpl(
startOffset, endOffset, origin, symbol,
name, if (index < 0) 0 else index,
isReified,
variance
).apply {
descriptor.bind(this)
}
}
}
// Cache the type parameter BEFORE processing its bounds/supertypes, to properly handle recursive type bounds.
if (typeContext.origin == ConversionTypeOrigin.SETTER) {
typeParameterCacheForSetter[typeParameter] = irTypeParameter
} else {
typeParameterCache[typeParameter] = irTypeParameter
}
bounds.mapTo(irTypeParameter.superTypes) { it.toIrType() }
irTypeParameter
}
}
fun putEnumEntryClassInScope(enumEntry: FirEnumEntry, correspondingClass: IrClass) {
localStorage.putLocalClass(enumEntry.initializer as FirAnonymousObject, correspondingClass)
}
fun getCachedIrEnumEntry(enumEntry: FirEnumEntry): IrEnumEntry? = enumEntryCache[enumEntry]
fun createIrEnumEntry(
enumEntry: FirEnumEntry,
irParent: IrClass?,
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED
): IrEnumEntry {
return enumEntry.convertWithOffsets { startOffset, endOffset ->
val desc = WrappedEnumEntryDescriptor()
declarationStorage.enterScope(desc)
val result = irSymbolTable.declareEnumEntry(startOffset, endOffset, origin, desc) { symbol ->
IrEnumEntryImpl(
startOffset, endOffset, origin, symbol, enumEntry.name
).apply {
desc.bind(this)
val irType = enumEntry.returnTypeRef.toIrType()
if (irParent != null) {
this.parent = irParent
}
val initializer = enumEntry.initializer
if (initializer != null) {
initializer as FirAnonymousObject
val klass = getIrAnonymousObjectForEnumEntry(initializer, enumEntry.name, irParent)
this.correspondingClass = klass
} else if (irParent != null) {
this.initializerExpression = IrExpressionBodyImpl(
IrEnumConstructorCallImpl(startOffset, endOffset, irType, irParent.constructors.first().symbol)
)
}
}
}
declarationStorage.leaveScope(desc)
enumEntryCache[enumEntry] = result
result
}
}
fun getIrClassSymbol(firClassSymbol: FirClassSymbol<*>): IrClassSymbol {
val firClass = firClassSymbol.fir
getCachedIrClass(firClass)?.let { return irSymbolTable.referenceClass(it.descriptor) }
// TODO: remove all this code and change to unbound symbol creation
val irClass = createIrClass(firClass)
if (firClass is FirAnonymousObject || firClass is FirRegularClass && firClass.visibility == Visibilities.LOCAL) {
return irSymbolTable.referenceClass(irClass.descriptor)
}
val classId = firClassSymbol.classId
val parentId = classId.outerClassId
val irParent = declarationStorage.findIrParent(classId.packageFqName, parentId, firClassSymbol)
if (irParent != null) {
irClass.parent = irParent
}
if (irParent is IrExternalPackageFragment) {
declarationStorage.addDeclarationsToExternalClass(firClass as FirRegularClass, irClass)
}
return irSymbolTable.referenceClass(irClass.descriptor)
}
fun getIrTypeParameterSymbol(
firTypeParameterSymbol: FirTypeParameterSymbol,
typeContext: ConversionTypeContext
): IrTypeParameterSymbol {
// TODO: use cached type parameter here
val irTypeParameter = getIrTypeParameter(firTypeParameterSymbol.fir, typeContext = typeContext)
return irSymbolTable.referenceTypeParameter(irTypeParameter.descriptor)
}
}

View File

@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.psi2ir.PsiSourceManager
class Fir2IrConverter(
private val moduleDescriptor: FirModuleDescriptor,
private val sourceManager: PsiSourceManager,
private val classifierStorage: Fir2IrClassifierStorage,
private val declarationStorage: Fir2IrDeclarationStorage
) {
@@ -71,7 +72,7 @@ class Fir2IrConverter(
fun processAnonymousObjectMembers(
anonymousObject: FirAnonymousObject,
irClass: IrClass = declarationStorage.getCachedIrClass(anonymousObject)!!
irClass: IrClass = classifierStorage.getCachedIrClass(anonymousObject)!!
): IrClass {
anonymousObject.getPrimaryConstructorIfAny()?.let {
irClass.declarations += declarationStorage.createIrConstructor(it, irClass)
@@ -89,7 +90,7 @@ class Fir2IrConverter(
private fun processClassMembers(
regularClass: FirRegularClass,
irClass: IrClass = declarationStorage.getCachedIrClass(regularClass)!!
irClass: IrClass = classifierStorage.getCachedIrClass(regularClass)!!
): IrClass {
regularClass.getPrimaryConstructorIfAny()?.let {
irClass.declarations += declarationStorage.createIrConstructor(it, irClass)
@@ -102,7 +103,7 @@ class Fir2IrConverter(
}
private fun registerClassAndNestedClasses(regularClass: FirRegularClass, parent: IrDeclarationParent): IrClass {
val irClass = declarationStorage.registerIrClass(regularClass, parent)
val irClass = classifierStorage.registerIrClass(regularClass, parent)
regularClass.declarations.forEach {
if (it is FirRegularClass) {
registerClassAndNestedClasses(it, irClass)
@@ -112,7 +113,7 @@ class Fir2IrConverter(
}
private fun processClassAndNestedClassHeaders(regularClass: FirRegularClass) {
declarationStorage.processClassHeader(regularClass)
classifierStorage.processClassHeader(regularClass)
regularClass.declarations.forEach {
if (it is FirRegularClass) {
processClassAndNestedClassHeaders(it)
@@ -137,7 +138,7 @@ class Fir2IrConverter(
null
}
is FirEnumEntry -> {
declarationStorage.createIrEnumEntry(declaration, parent as IrClass)
classifierStorage.createIrEnumEntry(declaration, parent as IrClass)
}
is FirAnonymousInitializer -> {
declarationStorage.createIrAnonymousInitializer(declaration, parent as IrClass)
@@ -169,12 +170,16 @@ class Fir2IrConverter(
val builtIns = IrBuiltIns(moduleDescriptor.builtIns, typeTranslator, signaturer, symbolTable)
val sourceManager = PsiSourceManager()
val declarationStorage = Fir2IrDeclarationStorage(session, symbolTable, moduleDescriptor)
val typeConverter = Fir2IrTypeConverter(session, declarationStorage, builtIns)
val classifierStorage = Fir2IrClassifierStorage(session, symbolTable)
val typeConverter = Fir2IrTypeConverter(session, classifierStorage, builtIns)
declarationStorage.typeConverter = typeConverter
classifierStorage.typeConverter = typeConverter
declarationStorage.classifierStorage = classifierStorage
classifierStorage.declarationStorage = declarationStorage
typeConverter.initBuiltinTypes()
val irFiles = mutableListOf<IrFile>()
val converter = Fir2IrConverter(moduleDescriptor, sourceManager, declarationStorage)
val converter = Fir2IrConverter(moduleDescriptor, sourceManager, classifierStorage, declarationStorage)
for (firFile in firFiles) {
converter.registerFileAndClasses(firFile)
}
@@ -186,7 +191,7 @@ class Fir2IrConverter(
}
val fir2irVisitor = Fir2IrVisitor(
session, symbolTable, declarationStorage, converter, typeConverter, builtIns, fakeOverrideMode
session, symbolTable, classifierStorage, declarationStorage, converter, typeConverter, builtIns, fakeOverrideMode
)
for (firFile in firFiles) {
val irFile = firFile.accept(fir2irVisitor, null) as IrFile

View File

@@ -5,7 +5,9 @@
package org.jetbrains.kotlin.fir.backend
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter
@@ -28,14 +30,11 @@ import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.*
import org.jetbrains.kotlin.ir.descriptors.*
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrEnumConstructorCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.util.constructors
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
@@ -56,12 +55,6 @@ class Fir2IrDeclarationStorage(
private val fileCache = mutableMapOf<FirFile, IrFile>()
private val classCache = mutableMapOf<FirRegularClass, IrClass>()
private val typeParameterCache = mutableMapOf<FirTypeParameter, IrTypeParameter>()
private val typeParameterCacheForSetter = mutableMapOf<FirTypeParameter, IrTypeParameter>()
private val functionCache = mutableMapOf<FirFunction<*>, IrSimpleFunction>()
private val constructorCache = mutableMapOf<FirConstructor, IrConstructor>()
@@ -72,12 +65,12 @@ class Fir2IrDeclarationStorage(
private val fieldCache = mutableMapOf<FirField, IrField>()
private val enumEntryCache = mutableMapOf<FirEnumEntry, IrEnumEntry>()
private val localStorage = Fir2IrLocalStorage()
lateinit var typeConverter: Fir2IrTypeConverter
lateinit var classifierStorage: Fir2IrClassifierStorage
fun registerFile(firFile: FirFile, irFile: IrFile) {
fileCache[firFile] = irFile
}
@@ -121,68 +114,7 @@ class Fir2IrDeclarationStorage(
}
}
private fun IrDeclaration.declareThisReceiverParameter(
parent: IrDeclarationParent,
thisType: IrType,
thisOrigin: IrDeclarationOrigin,
startOffset: Int = this.startOffset,
endOffset: Int = this.endOffset
): IrValueParameter {
val receiverDescriptor = WrappedReceiverParameterDescriptor()
return irSymbolTable.declareValueParameter(
startOffset, endOffset, thisOrigin, receiverDescriptor, thisType
) { symbol ->
IrValueParameterImpl(
startOffset, endOffset, thisOrigin, symbol,
Name.special("<this>"), -1, thisType,
varargElementType = null, isCrossinline = false, isNoinline = false
).apply {
this.parent = parent
receiverDescriptor.bind(this)
}
}
}
private fun IrClass.setThisReceiver() {
enterScope(descriptor)
val typeArguments = this.typeParameters.map {
IrSimpleTypeImpl(it.symbol, false, emptyList(), emptyList())
}
thisReceiver = declareThisReceiverParameter(
parent = this,
thisType = IrSimpleTypeImpl(symbol, false, typeArguments, emptyList()),
thisOrigin = IrDeclarationOrigin.INSTANCE_RECEIVER
)
leaveScope(descriptor)
}
private fun preCacheTypeParameters(owner: FirTypeParametersOwner) {
owner.typeParameters.mapIndexed { index, typeParameter ->
getIrTypeParameter(typeParameter, index)
if (owner is FirProperty && owner.isVar) {
getIrTypeParameter(typeParameter, index, ConversionTypeContext.DEFAULT.inSetter())
}
}
}
private fun IrTypeParametersContainer.setTypeParameters(
owner: FirTypeParametersOwner,
typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT
) {
typeParameters = owner.typeParameters.mapIndexed { index, typeParameter ->
getIrTypeParameter(typeParameter, index, typeContext).apply { parent = this@setTypeParameters }
}
}
private fun IrClass.declareSupertypesAndTypeParameters(klass: FirClass<*>): IrClass {
if (klass is FirRegularClass) {
setTypeParameters(klass)
}
superTypes = klass.superTypeRefs.map { superTypeRef -> superTypeRef.toIrType() }
return this
}
private fun addDeclarationsToExternalClass(regularClass: FirRegularClass, irClass: IrClass) {
internal fun addDeclarationsToExternalClass(regularClass: FirRegularClass, irClass: IrClass) {
if (regularClass.symbol.classId.packageFqName.startsWith(Name.identifier("kotlin"))) {
// Note: yet this is necessary only for *Range / *Progression classes
// due to BE optimizations (for lowering) that use their first / last / step members
@@ -202,7 +134,7 @@ class Fir2IrDeclarationStorage(
createIrConstructor(declaration, irClass)
}
is FirRegularClass -> {
createIrClass(declaration, irClass)
classifierStorage.createIrClass(declaration, irClass)
}
else -> continue
}
@@ -235,190 +167,12 @@ class Fir2IrDeclarationStorage(
}
}
fun getCachedIrClass(klass: FirClass<*>): IrClass? {
return if (klass is FirAnonymousObject || klass is FirRegularClass && klass.visibility == Visibilities.LOCAL) {
localStorage.getLocalClass(klass)
} else {
classCache[klass]
}
}
private fun FirRegularClass.enumClassModality(): Modality {
return when {
declarations.any { it is FirCallableMemberDeclaration<*> && it.modality == Modality.ABSTRACT } -> {
Modality.ABSTRACT
}
declarations.any { it is FirEnumEntry && it.initializer != null } -> {
Modality.OPEN
}
else -> {
Modality.FINAL
}
}
}
private fun createIrClass(klass: FirClass<*>, parent: IrDeclarationParent? = null): IrClass {
// NB: klass can be either FirRegularClass or FirAnonymousObject
if (klass is FirAnonymousObject) {
return createIrAnonymousObject(klass, irParent = parent)
}
val regularClass = klass as FirRegularClass
val origin =
if (firProvider.getFirClassifierContainerFileIfAny(klass.symbol) != null) IrDeclarationOrigin.DEFINED
else IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB
val irClass = registerIrClass(regularClass, parent, origin)
processClassHeader(regularClass, irClass)
return irClass
}
fun processClassHeader(regularClass: FirRegularClass, irClass: IrClass = getCachedIrClass(regularClass)!!): IrClass {
irClass.declareSupertypesAndTypeParameters(regularClass)
irClass.setThisReceiver()
return irClass
}
fun registerIrClass(
regularClass: FirRegularClass,
parent: IrDeclarationParent? = null,
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED
): IrClass {
val descriptor = WrappedClassDescriptor()
val visibility = regularClass.visibility
val modality = if (regularClass.classKind == ClassKind.ENUM_CLASS) {
regularClass.enumClassModality()
} else {
regularClass.modality ?: Modality.FINAL
}
val irClass = regularClass.convertWithOffsets { startOffset, endOffset ->
irSymbolTable.declareClass(startOffset, endOffset, origin, descriptor, modality, visibility) { symbol ->
IrClassImpl(
startOffset,
endOffset,
origin,
symbol,
regularClass.name,
regularClass.classKind,
visibility,
modality,
isCompanion = regularClass.isCompanion,
isInner = regularClass.isInner,
isData = regularClass.isData,
isExternal = regularClass.isExternal,
isInline = regularClass.isInline,
isExpect = regularClass.isExpect,
isFun = false // TODO FirRegularClass.isFun
).apply {
descriptor.bind(this)
}
}
}
if (parent != null) {
irClass.parent = parent
}
if (regularClass.visibility == Visibilities.LOCAL) {
localStorage.putLocalClass(regularClass, irClass)
} else {
classCache[regularClass] = irClass
}
return irClass
}
fun createIrAnonymousObject(
anonymousObject: FirAnonymousObject,
visibility: Visibility = Visibilities.LOCAL,
name: Name = Name.special("<no name provided>"),
irParent: IrDeclarationParent? = null
): IrClass {
val descriptor = WrappedClassDescriptor()
val origin = IrDeclarationOrigin.DEFINED
val modality = Modality.FINAL
val result = anonymousObject.convertWithOffsets { startOffset, endOffset ->
irSymbolTable.declareClass(startOffset, endOffset, origin, descriptor, modality, visibility) { symbol ->
IrClassImpl(
startOffset, endOffset, origin, symbol, name,
// NB: for unknown reason, IR uses 'CLASS' kind for simple anonymous objects
anonymousObject.classKind.takeIf { it == ClassKind.ENUM_ENTRY } ?: ClassKind.CLASS,
visibility, modality,
isCompanion = false, isInner = false, isData = false,
isExternal = false, isInline = false, isExpect = false, isFun = false
).apply {
descriptor.bind(this)
setThisReceiver()
if (irParent != null) {
this.parent = irParent
}
}
}
}.declareSupertypesAndTypeParameters(anonymousObject)
localStorage.putLocalClass(anonymousObject, result)
return result
}
private fun getIrAnonymousObjectForEnumEntry(anonymousObject: FirAnonymousObject, name: Name, irParent: IrClass?): IrClass {
localStorage.getLocalClass(anonymousObject)?.let { return it }
return createIrAnonymousObject(anonymousObject, Visibilities.PRIVATE, name, irParent)
}
private fun getIrTypeParameter(
typeParameter: FirTypeParameter,
index: Int = -1,
typeContext: ConversionTypeContext = ConversionTypeContext.DEFAULT
): IrTypeParameter {
// Here transformation is a bit difficult because one FIR property type parameter
// can be transformed to two different type parameters: one for getter and another one for setter
val simpleCachedParameter = typeParameterCache[typeParameter]
if (simpleCachedParameter != null) {
if (typeContext.origin != ConversionTypeOrigin.SETTER) {
return simpleCachedParameter
}
if (index < 0) {
val parent = simpleCachedParameter.parent
if (parent !is IrSimpleFunction || parent.returnType == typeConverter.unitType) {
return simpleCachedParameter
}
}
}
if (typeContext.origin == ConversionTypeOrigin.SETTER) {
typeParameterCacheForSetter[typeParameter]?.let { return it }
}
return typeParameter.run {
// Yet I don't want to enable this requirement because it breaks some tests
// However, if we get here it *should* mean that type parameter index is given explicitly
// At this moment (20.02.2020) this requirement breaks 11/355 Fir2IrText tests
// require(index != -1)
val descriptor = WrappedTypeParameterDescriptor()
val origin = IrDeclarationOrigin.DEFINED
val irTypeParameter =
convertWithOffsets { startOffset, endOffset ->
irSymbolTable.declareGlobalTypeParameter(startOffset, endOffset, origin, descriptor) { symbol ->
IrTypeParameterImpl(
startOffset, endOffset, origin, symbol,
name, if (index < 0) 0 else index,
isReified,
variance
).apply {
descriptor.bind(this)
}
}
}
// Cache the type parameter BEFORE processing its bounds/supertypes, to properly handle recursive type bounds.
if (typeContext.origin == ConversionTypeOrigin.SETTER) {
typeParameterCacheForSetter[typeParameter] = irTypeParameter
} else {
typeParameterCache[typeParameter] = irTypeParameter
}
bounds.mapTo(irTypeParameter.superTypes) { it.toIrType() }
irTypeParameter
}
}
private fun findIrParent(packageFqName: FqName, parentClassId: ClassId?, firBasedSymbol: FirBasedSymbol<*>): IrDeclarationParent? {
internal fun findIrParent(packageFqName: FqName, parentClassId: ClassId?, firBasedSymbol: FirBasedSymbol<*>): IrDeclarationParent? {
return if (parentClassId != null) {
// TODO: this will never work for local classes
val parentFirSymbol = firSymbolProvider.getClassLikeSymbolByFqName(parentClassId)
if (parentFirSymbol is FirClassSymbol) {
val parentIrSymbol = getIrClassSymbol(parentFirSymbol)
val parentIrSymbol = classifierStorage.getIrClassSymbol(parentFirSymbol)
parentIrSymbol.owner
} else {
null
@@ -485,7 +239,9 @@ class Fir2IrDeclarationStorage(
) {
val parent = this
if (function is FirSimpleFunction) {
setTypeParameters(function)
with(classifierStorage) {
setTypeParameters(function)
}
}
val forSetter = function is FirPropertyAccessor && function.isSetter
val typeContext = ConversionTypeContext(
@@ -509,24 +265,26 @@ class Fir2IrDeclarationStorage(
if (function !is FirConstructor) {
val thisOrigin = IrDeclarationOrigin.DEFINED
val receiverTypeRef = if (function !is FirPropertyAccessor) function?.receiverTypeRef else parentPropertyReceiverType
if (receiverTypeRef != null) {
extensionReceiverParameter = receiverTypeRef.convertWithOffsets { startOffset, endOffset ->
declareThisReceiverParameter(
with(classifierStorage) {
if (receiverTypeRef != null) {
extensionReceiverParameter = receiverTypeRef.convertWithOffsets { startOffset, endOffset ->
declareThisReceiverParameter(
parent,
thisType = receiverTypeRef.toIrType(typeContext),
thisOrigin = thisOrigin,
startOffset = startOffset,
endOffset = endOffset
)
}
}
if (function !is FirAnonymousFunction && containingClass != null && !isStatic) {
dispatchReceiverParameter = declareThisReceiverParameter(
parent,
thisType = receiverTypeRef.toIrType(typeContext),
thisOrigin = thisOrigin,
startOffset = startOffset,
endOffset = endOffset
thisType = containingClass.thisReceiver!!.type,
thisOrigin = thisOrigin
)
}
}
if (function !is FirAnonymousFunction && containingClass != null && !isStatic) {
dispatchReceiverParameter = declareThisReceiverParameter(
parent,
thisType = containingClass.thisReceiver!!.type,
thisOrigin = thisOrigin
)
}
}
}
@@ -552,10 +310,6 @@ class Fir2IrDeclarationStorage(
return this
}
fun putEnumEntryClassInScope(enumEntry: FirEnumEntry, correspondingClass: IrClass) {
localStorage.putLocalClass(enumEntry.initializer as FirAnonymousObject, correspondingClass)
}
fun getCachedIrFunction(function: FirFunction<*>): IrSimpleFunction? {
return if (function !is FirSimpleFunction || function.visibility == Visibilities.LOCAL) {
localStorage.getLocalFunction(function)
@@ -578,7 +332,7 @@ class Fir2IrDeclarationStorage(
function.symbol.callableId.isKFunctionInvoke() -> IrDeclarationOrigin.FAKE_OVERRIDE
else -> origin
}
preCacheTypeParameters(function)
classifierStorage.preCacheTypeParameters(function)
val name = simpleFunction?.name
?: if (isLambda) Name.special("<anonymous>") else Name.special("<no name provided>")
val visibility = simpleFunction?.visibility ?: Visibilities.LOCAL
@@ -694,12 +448,14 @@ class Fir2IrDeclarationStorage(
isFakeOverride = origin == IrDeclarationOrigin.FAKE_OVERRIDE,
isOperator = false
).apply {
setTypeParameters(
property, ConversionTypeContext(
definitelyNotNull = false,
origin = if (isSetter) ConversionTypeOrigin.SETTER else ConversionTypeOrigin.DEFAULT
with(classifierStorage) {
setTypeParameters(
property, ConversionTypeContext(
definitelyNotNull = false,
origin = if (isSetter) ConversionTypeOrigin.SETTER else ConversionTypeOrigin.DEFAULT
)
)
)
}
if (propertyAccessor == null && isSetter) {
declareDefaultSetterParameter(
property.returnTypeRef.toIrType(ConversionTypeContext.DEFAULT.inSetter())
@@ -719,44 +475,6 @@ class Fir2IrDeclarationStorage(
}
}
fun getCachedIrEnumEntry(enumEntry: FirEnumEntry): IrEnumEntry? = enumEntryCache[enumEntry]
fun createIrEnumEntry(
enumEntry: FirEnumEntry,
irParent: IrClass?,
origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED
): IrEnumEntry {
return enumEntry.convertWithOffsets { startOffset, endOffset ->
val desc = WrappedEnumEntryDescriptor()
enterScope(desc)
val result = irSymbolTable.declareEnumEntry(startOffset, endOffset, origin, desc) { symbol ->
IrEnumEntryImpl(
startOffset, endOffset, origin, symbol, enumEntry.name
).apply {
desc.bind(this)
val irType = enumEntry.returnTypeRef.toIrType()
if (irParent != null) {
this.parent = irParent
}
val initializer = enumEntry.initializer
if (initializer != null) {
initializer as FirAnonymousObject
val klass = getIrAnonymousObjectForEnumEntry(initializer, enumEntry.name, irParent)
this.correspondingClass = klass
} else if (irParent != null) {
this.initializerExpression = IrExpressionBodyImpl(
IrEnumConstructorCallImpl(startOffset, endOffset, irType, irParent.constructors.first().symbol)
)
}
}
}
leaveScope(desc)
enumEntryCache[enumEntry] = result
result
}
}
fun createIrProperty(
property: FirProperty,
irParent: IrDeclarationParent?,
@@ -764,7 +482,7 @@ class Fir2IrDeclarationStorage(
): IrProperty {
val containerSource = property.containerSource
val descriptor = containerSource?.let { WrappedPropertyDescriptorWithContainerSource(it) } ?: WrappedPropertyDescriptor()
preCacheTypeParameters(property)
classifierStorage.preCacheTypeParameters(property)
return property.convertWithOffsets { startOffset, endOffset ->
enterScope(descriptor)
val result = irSymbolTable.declareProperty(
@@ -936,36 +654,6 @@ class Fir2IrDeclarationStorage(
}
}
fun getIrClassSymbol(firClassSymbol: FirClassSymbol<*>): IrClassSymbol {
val firClass = firClassSymbol.fir
getCachedIrClass(firClass)?.let { return irSymbolTable.referenceClass(it.descriptor) }
// TODO: remove all this code and change to unbound symbol creation
val irClass = createIrClass(firClass)
if (firClass is FirAnonymousObject || firClass is FirRegularClass && firClass.visibility == Visibilities.LOCAL) {
return irSymbolTable.referenceClass(irClass.descriptor)
}
val classId = firClassSymbol.classId
val parentId = classId.outerClassId
val irParent = findIrParent(classId.packageFqName, parentId, firClassSymbol)
if (irParent != null) {
irClass.parent = irParent
}
if (irParent is IrExternalPackageFragment) {
addDeclarationsToExternalClass(firClass as FirRegularClass, irClass)
}
return irSymbolTable.referenceClass(irClass.descriptor)
}
fun getIrTypeParameterSymbol(
firTypeParameterSymbol: FirTypeParameterSymbol,
typeContext: ConversionTypeContext
): IrTypeParameterSymbol {
// TODO: use cached type parameter here
val irTypeParameter = getIrTypeParameter(firTypeParameterSymbol.fir, typeContext = typeContext)
return irSymbolTable.referenceTypeParameter(irTypeParameter.descriptor)
}
fun getIrConstructorSymbol(firConstructorSymbol: FirConstructorSymbol): IrConstructorSymbol {
val firConstructor = firConstructorSymbol.fir
getCachedIrConstructor(firConstructor)?.let { return irSymbolTable.referenceConstructor(it.descriptor) }
@@ -1043,11 +731,11 @@ class Fir2IrDeclarationStorage(
fun getIrValueSymbol(firVariableSymbol: FirVariableSymbol<*>): IrSymbol {
return when (val firDeclaration = firVariableSymbol.fir) {
is FirEnumEntry -> {
getCachedIrEnumEntry(firDeclaration)?.let { return irSymbolTable.referenceEnumEntry(it.descriptor) }
classifierStorage.getCachedIrEnumEntry(firDeclaration)?.let { return irSymbolTable.referenceEnumEntry(it.descriptor) }
val containingFile = firProvider.getFirCallableContainerFile(firVariableSymbol)
val parentClassSymbol = firVariableSymbol.callableId.classId?.let { firSymbolProvider.getClassLikeSymbolByFqName(it) }
val irParentClass = (parentClassSymbol?.fir as? FirClass<*>)?.let { getCachedIrClass(it) }
val irEnumEntry = createIrEnumEntry(
val irParentClass = (parentClassSymbol?.fir as? FirClass<*>)?.let { classifierStorage.getCachedIrClass(it) }
val irEnumEntry = classifierStorage.createIrEnumEntry(
firDeclaration,
irParent = irParentClass,
origin = if (containingFile == null) IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB else IrDeclarationOrigin.DEFINED

View File

@@ -21,7 +21,7 @@ import org.jetbrains.kotlin.types.Variance
class Fir2IrTypeConverter(
private val session: FirSession,
private val declarationStorage: Fir2IrDeclarationStorage,
private val classifierStorage: Fir2IrClassifierStorage,
private val irBuiltIns: IrBuiltIns
) {
lateinit var nothingType: IrType
@@ -49,7 +49,7 @@ class Fir2IrTypeConverter(
is ConeLookupTagBasedType -> {
val irSymbol = getArrayType(this.classId) ?: run {
val firSymbol = this.lookupTag.toSymbol(session) ?: return createErrorType()
firSymbol.toIrSymbol(session, declarationStorage, typeContext)
firSymbol.toSymbol(session, classifierStorage, typeContext)
}
// TODO: annotations
IrSimpleTypeImpl(

View File

@@ -47,6 +47,7 @@ import java.util.*
class Fir2IrVisitor(
private val session: FirSession,
private val symbolTable: SymbolTable,
private val classifierStorage: Fir2IrClassifierStorage,
private val declarationStorage: Fir2IrDeclarationStorage,
private val converter: Fir2IrConverter,
private val typeConverter: Fir2IrTypeConverter,
@@ -95,10 +96,10 @@ class Fir2IrVisitor(
// ==================================================================================
override fun visitEnumEntry(enumEntry: FirEnumEntry, data: Any?): IrElement {
val irEnumEntry = declarationStorage.getCachedIrEnumEntry(enumEntry)!!
val irEnumEntry = classifierStorage.getCachedIrEnumEntry(enumEntry)!!
val correspondingClass = irEnumEntry.correspondingClass ?: return irEnumEntry
declarationStorage.enterScope(irEnumEntry.descriptor)
declarationStorage.putEnumEntryClassInScope(enumEntry, correspondingClass)
classifierStorage.putEnumEntryClassInScope(enumEntry, correspondingClass)
converter.processAnonymousObjectMembers(enumEntry.initializer as FirAnonymousObject, correspondingClass)
conversionScope.withParent(correspondingClass) {
setClassContent(enumEntry.initializer as FirAnonymousObject)
@@ -150,7 +151,7 @@ class Fir2IrVisitor(
override fun visitRegularClass(regularClass: FirRegularClass, data: Any?): IrElement {
if (regularClass.visibility == Visibilities.LOCAL) {
val irParent = conversionScope.parentFromStack()
val irClass = declarationStorage.getCachedIrClass(regularClass)?.apply { this.parent = irParent }
val irClass = classifierStorage.getCachedIrClass(regularClass)?.apply { this.parent = irParent }
if (irClass != null) {
converter.processRegisteredLocalClassAndNestedClasses(regularClass, irClass)
return conversionScope.withParent(irClass) {
@@ -159,7 +160,7 @@ class Fir2IrVisitor(
}
converter.processLocalClassAndNestedClasses(regularClass, irParent)
}
val irClass = declarationStorage.getCachedIrClass(regularClass)!!
val irClass = classifierStorage.getCachedIrClass(regularClass)!!
return conversionScope.withParent(irClass) {
setClassContent(regularClass)
}
@@ -168,8 +169,8 @@ class Fir2IrVisitor(
override fun visitAnonymousObject(anonymousObject: FirAnonymousObject, data: Any?): IrElement {
val irParent = conversionScope.parentFromStack()
// NB: for implicit types it is possible that anonymous object is already cached
val irAnonymousObject = declarationStorage.getCachedIrClass(anonymousObject)?.apply { this.parent = irParent }
?: declarationStorage.createIrAnonymousObject(anonymousObject, irParent = irParent)
val irAnonymousObject = classifierStorage.getCachedIrClass(anonymousObject)?.apply { this.parent = irParent }
?: classifierStorage.createIrAnonymousObject(anonymousObject, irParent = irParent)
converter.processAnonymousObjectMembers(anonymousObject, irAnonymousObject)
conversionScope.withParent(irAnonymousObject) {
setClassContent(anonymousObject)
@@ -499,7 +500,7 @@ class Fir2IrVisitor(
private fun FirQualifiedAccess.toIrExpression(typeRef: FirTypeRef): IrExpression {
val type = typeRef.toIrType()
val symbol = calleeReference.toSymbol(declarationStorage)
val symbol = calleeReference.toSymbol(session, classifierStorage, declarationStorage)
return typeRef.convertWithOffsets { startOffset, endOffset ->
if (calleeReference is FirSuperReference) {
if (typeRef !is FirComposedSuperTypeRef) {
@@ -647,7 +648,7 @@ class Fir2IrVisitor(
it is FirAnonymousObject || it is FirRegularClass && it.classKind == ClassKind.OBJECT
}
firClass?.convertWithOffsets { startOffset, endOffset ->
val irClass = declarationStorage.getCachedIrClass(firClass)!!
val irClass = classifierStorage.getCachedIrClass(firClass)!!
IrGetObjectValueImpl(startOffset, endOffset, irClass.defaultType, irClass.symbol)
}
}
@@ -715,7 +716,7 @@ class Fir2IrVisitor(
it is FirAnonymousObject || it is FirRegularClass && it.classKind == ClassKind.OBJECT
}
if (firObject != null) {
val irObject = declarationStorage.getCachedIrClass(firObject)!!
val irObject = classifierStorage.getCachedIrClass(firObject)!!
if (irObject != conversionScope.lastClass()) {
return thisReceiverExpression.convertWithOffsets { startOffset, endOffset ->
IrGetObjectValueImpl(startOffset, endOffset, irObject.defaultType, irObject.symbol)
@@ -750,7 +751,7 @@ class Fir2IrVisitor(
}
override fun visitCallableReferenceAccess(callableReferenceAccess: FirCallableReferenceAccess, data: Any?): IrElement {
val symbol = callableReferenceAccess.calleeReference.toSymbol(declarationStorage)
val symbol = callableReferenceAccess.calleeReference.toSymbol(session, classifierStorage, declarationStorage)
val type = callableReferenceAccess.typeRef.toIrType()
return callableReferenceAccess.convertWithOffsets { startOffset, endOffset ->
when (symbol) {
@@ -792,7 +793,7 @@ class Fir2IrVisitor(
override fun visitVariableAssignment(variableAssignment: FirVariableAssignment, data: Any?): IrElement {
val calleeReference = variableAssignment.calleeReference
val symbol = calleeReference.toSymbol(declarationStorage)
val symbol = calleeReference.toSymbol(session, classifierStorage, declarationStorage)
return variableAssignment.convertWithOffsets { startOffset, endOffset ->
if (symbol != null && symbol.isBound) {
when (symbol) {
@@ -1235,7 +1236,7 @@ class Fir2IrVisitor(
val irClassType = argument.typeRef.toIrType()
val irClassReferenceSymbol = when (argument) {
is FirResolvedReifiedParameterReference -> {
declarationStorage.getIrTypeParameterSymbol(argument.symbol, ConversionTypeContext.DEFAULT)
classifierStorage.getIrTypeParameterSymbol(argument.symbol, ConversionTypeContext.DEFAULT)
}
is FirResolvedQualifier -> {
val symbol = argument.symbol as? FirClassSymbol
@@ -1244,7 +1245,7 @@ class Fir2IrVisitor(
startOffset, endOffset, irType, "Resolved qualifier ${argument.render()} does not have correct symbol"
)
}
declarationStorage.getIrClassSymbol(symbol)
classifierStorage.getIrClassSymbol(symbol)
}
else -> null
}
@@ -1274,7 +1275,7 @@ class Fir2IrVisitor(
if (classSymbol != null) {
IrGetObjectValueImpl(
startOffset, endOffset, irType,
classSymbol.toIrSymbol(session, declarationStorage) as IrClassSymbol
classSymbol.toSymbol(session, classifierStorage) as IrClassSymbol
)
} else {
IrErrorCallExpressionImpl(