[FIR2IR] Don't create IR properties when their symbol is referenced

KT-62856
This commit is contained in:
Dmitriy Novozhilov
2023-11-14 15:43:41 +02:00
committed by Space Team
parent f0f8a9728e
commit 736201da1d
10 changed files with 254 additions and 212 deletions
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir.backend package org.jetbrains.kotlin.fir.backend
import com.intellij.util.containers.MultiMap
import org.jetbrains.kotlin.KtDiagnosticReporterWithImplicitIrBasedContext import org.jetbrains.kotlin.KtDiagnosticReporterWithImplicitIrBasedContext
import org.jetbrains.kotlin.KtFakeSourceElementKind import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.KtPsiSourceFileLinesMapping import org.jetbrains.kotlin.KtPsiSourceFileLinesMapping
@@ -23,16 +24,19 @@ import org.jetbrains.kotlin.fir.backend.generators.DataClassMembersGenerator
import org.jetbrains.kotlin.fir.backend.generators.addDeclarationToParent import org.jetbrains.kotlin.fir.backend.generators.addDeclarationToParent
import org.jetbrains.kotlin.fir.backend.generators.setParent import org.jetbrains.kotlin.fir.backend.generators.setParent
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.correspondingValueParameterFromPrimaryConstructor
import org.jetbrains.kotlin.fir.declarations.utils.isLocal import org.jetbrains.kotlin.fir.declarations.utils.isLocal
import org.jetbrains.kotlin.fir.declarations.utils.isSynthetic import org.jetbrains.kotlin.fir.declarations.utils.isSynthetic
import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor
import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.extensions.declarationGenerators import org.jetbrains.kotlin.fir.extensions.declarationGenerators
import org.jetbrains.kotlin.fir.extensions.extensionService import org.jetbrains.kotlin.fir.extensions.extensionService
import org.jetbrains.kotlin.fir.extensions.generatedMembers import org.jetbrains.kotlin.fir.extensions.generatedMembers
import org.jetbrains.kotlin.fir.extensions.generatedNestedClassifiers import org.jetbrains.kotlin.fir.extensions.generatedNestedClassifiers
import org.jetbrains.kotlin.fir.java.javaElementFinder import org.jetbrains.kotlin.fir.java.javaElementFinder
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyClass import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyClass
import org.jetbrains.kotlin.fir.references.toResolvedValueParameterSymbol
import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.symbols.lazyDeclarationResolver import org.jetbrains.kotlin.fir.symbols.lazyDeclarationResolver
import org.jetbrains.kotlin.fir.types.resolvedType import org.jetbrains.kotlin.fir.types.resolvedType
@@ -51,9 +55,9 @@ import org.jetbrains.kotlin.ir.interpreter.checker.EvaluationMode
import org.jetbrains.kotlin.ir.interpreter.transformer.transformConst import org.jetbrains.kotlin.ir.interpreter.transformer.transformConst
import org.jetbrains.kotlin.ir.overrides.IrFakeOverrideBuilder import org.jetbrains.kotlin.ir.overrides.IrFakeOverrideBuilder
import org.jetbrains.kotlin.ir.symbols.UnsafeDuringIrConstructionAPI import org.jetbrains.kotlin.ir.symbols.UnsafeDuringIrConstructionAPI
import org.jetbrains.kotlin.ir.types.IrTypeSystemContext
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorPublicSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorPublicSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionPublicSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionPublicSymbolImpl
import org.jetbrains.kotlin.ir.types.IrTypeSystemContext
import org.jetbrains.kotlin.ir.util.KotlinMangler import org.jetbrains.kotlin.ir.util.KotlinMangler
import org.jetbrains.kotlin.ir.util.NaiveSourceBasedFileEntryImpl import org.jetbrains.kotlin.ir.util.NaiveSourceBasedFileEntryImpl
import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.defaultType
@@ -198,7 +202,7 @@ class Fir2IrConverter(
private fun processFileAndClassMembers(file: FirFile) { private fun processFileAndClassMembers(file: FirFile) {
val irFile = declarationStorage.getIrFile(file) val irFile = declarationStorage.getIrFile(file)
for (declaration in file.declarations) { for (declaration in file.declarations) {
processMemberDeclaration(declaration, null, irFile) processMemberDeclaration(declaration, containingClass = null, irFile, delegateFieldToPropertyMap = null)
} }
} }
@@ -242,9 +246,12 @@ class Fir2IrConverter(
declarationStorage.createAndCacheIrConstructor(it.fir, { irClass }, isLocal = klass.isLocal) declarationStorage.createAndCacheIrConstructor(it.fir, { irClass }, isLocal = klass.isLocal)
} }
} }
val delegateFieldToPropertyMap = MultiMap<FirProperty, FirField>()
// At least on enum entry creation we may need a default constructor, so ctors should be converted first // At least on enum entry creation we may need a default constructor, so ctors should be converted first
for (declaration in syntheticPropertiesLast(allDeclarations)) { for (declaration in syntheticPropertiesLast(allDeclarations)) {
processMemberDeclaration(declaration, klass, irClass) processMemberDeclaration(declaration, klass, irClass, delegateFieldToPropertyMap)
} }
// Add delegated members *before* fake override generations. // Add delegated members *before* fake override generations.
// Otherwise, fake overrides for delegated members, which are redundant, will be added. // Otherwise, fake overrides for delegated members, which are redundant, will be added.
@@ -467,11 +474,17 @@ class Fir2IrConverter(
/** /**
* This function creates IR declarations for callable members without filling their body * This function creates IR declarations for callable members without filling their body
*
* @param delegateFieldToPropertyMap is needed to avoid problems with delegation to properties from primary constructor.
* The thing is that FirFields for delegates are declared before properties from the primary constructor, but in IR we don't
* create separate IrField for such fields and reuse the backing field of corresponding property.
* So, this map is used to postpone generation of delegated members until IR for corresponding property will be created
*/ */
private fun processMemberDeclaration( private fun processMemberDeclaration(
declaration: FirDeclaration, declaration: FirDeclaration,
containingClass: FirClass?, containingClass: FirClass?,
parent: IrDeclarationParent parent: IrDeclarationParent,
delegateFieldToPropertyMap: MultiMap<FirProperty, FirField>?
) { ) {
/* /*
* This function is needed to preserve the source order of declaration in file * This function is needed to preserve the source order of declaration in file
@@ -512,7 +525,7 @@ class Fir2IrConverter(
} }
for (scriptStatement in declaration.statements) { for (scriptStatement in declaration.statements) {
if (scriptStatement is FirDeclaration) { if (scriptStatement is FirDeclaration) {
processMemberDeclaration(scriptStatement, null, irScript) processMemberDeclaration(scriptStatement, containingClass = null, irScript, delegateFieldToPropertyMap = null)
} }
} }
} }
@@ -528,15 +541,35 @@ class Fir2IrConverter(
) { ) {
// Note: we have to do it, because backend without the feature // Note: we have to do it, because backend without the feature
// cannot process Enum.entries properly // cannot process Enum.entries properly
declarationStorage.getOrCreateIrProperty(declaration, parent, isLocal = isInLocalClass) val irProperty = declarationStorage.createAndCacheIrProperty(declaration, parent)
delegateFieldToPropertyMap?.remove(declaration)?.let { delegateFields ->
val backingField = irProperty.backingField!!
for (delegateField in delegateFields) {
declarationStorage.recordDelegateFieldMappedToBackingField(delegateField, backingField.symbol)
delegatedMemberGenerator.generateWithBodiesIfNeeded(
firField = delegateField,
irField = backingField,
containingClass!!,
parent as IrClass
)
}
}
} }
} }
is FirField -> { is FirField -> {
if (declaration.isSynthetic) { if (!declaration.isSynthetic) {
callablesGenerator.createIrFieldAndDelegatedMembers(declaration, containingClass!!, parent as IrClass)
} else {
error("Unexpected non-synthetic field: ${declaration::class}") error("Unexpected non-synthetic field: ${declaration::class}")
} }
requireNotNull(containingClass)
requireNotNull(delegateFieldToPropertyMap)
require(parent is IrClass)
val correspondingClassProperty = declaration.findCorrespondingDelegateProperty(containingClass)
if (correspondingClassProperty == null) {
val irField = declarationStorage.createDelegateIrField(declaration, parent)
delegatedMemberGenerator.generateWithBodiesIfNeeded(declaration, irField, containingClass, parent)
} else {
delegateFieldToPropertyMap.putValue(correspondingClassProperty, declaration)
}
} }
is FirConstructor -> if (!declaration.isPrimary) { is FirConstructor -> if (!declaration.isPrimary) {
// the primary constructor was already created in `processClassMembers` function // the primary constructor was already created in `processClassMembers` function
@@ -571,6 +604,16 @@ class Fir2IrConverter(
} }
} }
private fun FirField.findCorrespondingDelegateProperty(owner: FirClass): FirProperty? {
val initializer = this.initializer
if (initializer !is FirQualifiedAccessExpression) return null
if (initializer.explicitReceiver != null) return null
val resolvedSymbol = initializer.calleeReference.toResolvedValueParameterSymbol() ?: return null
return owner.declarations.filterIsInstance<FirProperty>().find {
it.correspondingValueParameterFromPrimaryConstructor == resolvedSymbol
}
}
companion object { companion object {
private fun evaluateConstants(irModuleFragment: IrModuleFragment, components: Fir2IrComponents) { private fun evaluateConstants(irModuleFragment: IrModuleFragment, components: Fir2IrComponents) {
val fir2IrConfiguration = components.configuration val fir2IrConfiguration = components.configuration
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.fir.backend package org.jetbrains.kotlin.fir.backend
import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.builtins.StandardNames.BUILT_INS_PACKAGE_FQ_NAMES import org.jetbrains.kotlin.builtins.StandardNames.BUILT_INS_PACKAGE_FQ_NAMES
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
@@ -14,21 +13,26 @@ import org.jetbrains.kotlin.fir.backend.generators.isExternalParent
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.buildProperty import org.jetbrains.kotlin.fir.declarations.builder.buildProperty
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
import org.jetbrains.kotlin.fir.declarations.utils.* import org.jetbrains.kotlin.fir.declarations.utils.hasBackingField
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
import org.jetbrains.kotlin.fir.declarations.utils.isStatic
import org.jetbrains.kotlin.fir.declarations.utils.visibility
import org.jetbrains.kotlin.fir.descriptors.FirBuiltInsPackageFragment import org.jetbrains.kotlin.fir.descriptors.FirBuiltInsPackageFragment
import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.java.symbols.FirJavaOverriddenSyntheticPropertySymbol import org.jetbrains.kotlin.fir.java.symbols.FirJavaOverriddenSyntheticPropertySymbol
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyClass import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyClass
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyProperty
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazySimpleFunction import org.jetbrains.kotlin.fir.lazy.Fir2IrLazySimpleFunction
import org.jetbrains.kotlin.fir.references.toResolvedValueParameterSymbol
import org.jetbrains.kotlin.fir.resolve.providers.firProvider import org.jetbrains.kotlin.fir.resolve.providers.firProvider
import org.jetbrains.kotlin.fir.resolve.toFirRegularClass import org.jetbrains.kotlin.fir.resolve.toFirRegularClass
import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.resolvedType
import org.jetbrains.kotlin.fir.types.toLookupTag
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.declarations.UNDEFINED_PARAMETER_INDEX import org.jetbrains.kotlin.ir.builders.declarations.UNDEFINED_PARAMETER_INDEX
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
@@ -50,7 +54,6 @@ import org.jetbrains.kotlin.utils.addToStdlib.runIf
import org.jetbrains.kotlin.utils.threadLocal import org.jetbrains.kotlin.utils.threadLocal
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
@OptIn(LeakedDeclarationCaches::class)
class Fir2IrDeclarationStorage( class Fir2IrDeclarationStorage(
private val components: Fir2IrComponents, private val components: Fir2IrComponents,
private val sourceModuleDescriptor: FirModuleDescriptor, private val sourceModuleDescriptor: FirModuleDescriptor,
@@ -470,36 +473,6 @@ class Fir2IrDeclarationStorage(
return prepareProperty(symbol.fir).symbol return prepareProperty(symbol.fir).symbol
} }
fun getOrCreateIrProperty(
property: FirProperty,
irParent: IrDeclarationParent?,
predefinedOrigin: IrDeclarationOrigin? = null,
isLocal: Boolean = false,
fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag? = null
): IrProperty {
return getOrCreateIrProperty(property, { irParent }, predefinedOrigin, isLocal, fakeOverrideOwnerLookupTag)
}
private fun getOrCreateIrProperty(
property: FirProperty,
irParent: () -> IrDeclarationParent?,
predefinedOrigin: IrDeclarationOrigin? = null,
isLocal: Boolean = false,
fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag? = null
): IrProperty {
@Suppress("NAME_SHADOWING")
val property = prepareProperty(property)
@OptIn(UnsafeDuringIrConstructionAPI::class)
getCachedIrPropertySymbol(property, fakeOverrideOwnerLookupTag)?.ownerIfBound()?.let { return it }
// See comment in [getOrCreateIrFunction]
if (fakeOverrideOwnerLookupTag != property.containingClassLookupTag()) {
generateLazyFakeOverrides(property.name, fakeOverrideOwnerLookupTag)
@OptIn(UnsafeDuringIrConstructionAPI::class)
getCachedIrPropertySymbol(property, fakeOverrideOwnerLookupTag)?.ownerIfBound()?.let { return it }
}
return createAndCacheIrProperty(property, irParent(), predefinedOrigin, isLocal, fakeOverrideOwnerLookupTag)
}
fun getOrCreateIrPropertyByPureField( fun getOrCreateIrPropertyByPureField(
field: FirField, field: FirField,
irParent: IrDeclarationParent irParent: IrDeclarationParent
@@ -509,32 +482,29 @@ class Fir2IrDeclarationStorage(
createAndCacheIrProperty( createAndCacheIrProperty(
field.toStubProperty(), field.toStubProperty(),
irParent, irParent,
fakeOverrideOwnerLookupTag = containingClassId?.toLookupTag() isLocal = false,
fakeOverrideOwnerLookupTag = containingClassId?.toLookupTag(),
allowLazyDeclarationsCreation = true // pure fields exist only in java
) )
} }
} }
@LeakedDeclarationCaches
fun createAndCacheIrProperty( fun createAndCacheIrProperty(
property: FirProperty, property: FirProperty,
irParent: IrDeclarationParent?, irParent: IrDeclarationParent?,
predefinedOrigin: IrDeclarationOrigin? = null, predefinedOrigin: IrDeclarationOrigin? = null,
isLocal: Boolean = false, isLocal: Boolean = false,
fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag? = null fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag? = null,
allowLazyDeclarationsCreation: Boolean = false
): IrProperty { ): IrProperty {
@Suppress("NAME_SHADOWING") @Suppress("NAME_SHADOWING")
val property = prepareProperty(property) val property = prepareProperty(property)
val signature = runIf(!isLocal && configuration.linkViaSignatures) { val symbols = getIrPropertySymbols(property.symbol, fakeOverrideOwnerLookupTag, isLocal)
signatureComposer.composeSignature(property, fakeOverrideOwnerLookupTag)
}
val symbols = createPropertySymbols(signature, property, fakeOverrideOwnerLookupTag) return callablesGenerator.createIrProperty(
val irProperty = callablesGenerator.createIrProperty( property, irParent, symbols, predefinedOrigin, fakeOverrideOwnerLookupTag, allowLazyDeclarationsCreation
property, irParent, symbols, predefinedOrigin, isLocal, fakeOverrideOwnerLookupTag
) )
cacheIrProperty(property, irProperty, fakeOverrideOwnerLookupTag)
return irProperty
} }
private fun createPropertySymbols( private fun createPropertySymbols(
@@ -572,21 +542,21 @@ class Fir2IrDeclarationStorage(
return PropertySymbols(propertySymbol, getterSymbol, setterSymbol, backingFieldSymbol) return PropertySymbols(propertySymbol, getterSymbol, setterSymbol, backingFieldSymbol)
} }
private fun cacheIrProperty( private fun cacheIrPropertySymbols(
property: FirProperty, property: FirProperty,
irProperty: IrProperty, symbols: PropertySymbols,
fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag?, fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag?,
) { ) {
val irPropertySymbol = irProperty.symbol val irPropertySymbol = symbols.propertySymbol
irProperty.backingField?.symbol?.let { symbols.backingFieldSymbol?.let {
backingFieldForPropertyCache[irPropertySymbol] = it backingFieldForPropertyCache[irPropertySymbol] = it
propertyForBackingFieldCache[it] = irPropertySymbol propertyForBackingFieldCache[it] = irPropertySymbol
} }
irProperty.getter?.let { symbols.getterSymbol.let {
getterForPropertyCache[irPropertySymbol] = it.symbol getterForPropertyCache[irPropertySymbol] = it
} }
irProperty.setter?.let { symbols.setterSymbol?.let {
setterForPropertyCache[irPropertySymbol] = it.symbol setterForPropertyCache[irPropertySymbol] = it
} }
if (property.isFakeOverrideOrDelegated(fakeOverrideOwnerLookupTag)) { if (property.isFakeOverrideOrDelegated(fakeOverrideOwnerLookupTag)) {
val originalProperty = property.unwrapFakeOverridesOrDelegated() val originalProperty = property.unwrapFakeOverridesOrDelegated()
@@ -594,9 +564,9 @@ class Fir2IrDeclarationStorage(
originalProperty.symbol, originalProperty.symbol,
fakeOverrideOwnerLookupTag ?: property.containingClassLookupTag()!! fakeOverrideOwnerLookupTag ?: property.containingClassLookupTag()!!
) )
irForFirSessionDependantDeclarationMap[key] = irProperty.symbol irForFirSessionDependantDeclarationMap[key] = irPropertySymbol
} else { } else {
propertyCache[property] = irProperty.symbol propertyCache[property] = irPropertySymbol
} }
} }
@@ -623,17 +593,51 @@ class Fir2IrDeclarationStorage(
fun getIrPropertySymbol( fun getIrPropertySymbol(
firPropertySymbol: FirPropertySymbol, firPropertySymbol: FirPropertySymbol,
fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag? = null, fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag? = null,
isLocal: Boolean = false
): IrSymbol { ): IrSymbol {
val firProperty = prepareProperty(firPropertySymbol.fir) val property = prepareProperty(firPropertySymbol.fir)
if (firProperty.isLocal) { if (property.isLocal) {
return localStorage.getDelegatedProperty(firProperty) ?: getIrVariableSymbol(firProperty) return localStorage.getDelegatedProperty(property) ?: getIrVariableSymbol(property)
} }
val result = getOrCreateIrProperty( getCachedIrPropertySymbol(property, fakeOverrideOwnerLookupTag)?.let { return it }
firProperty, return getIrPropertySymbols(firPropertySymbol, fakeOverrideOwnerLookupTag, isLocal).propertySymbol
{ findIrParent(firProperty, fakeOverrideOwnerLookupTag) }, }
fakeOverrideOwnerLookupTag = fakeOverrideOwnerLookupTag
) private fun getIrPropertySymbols(
return result.symbol firPropertySymbol: FirPropertySymbol,
fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag? = null,
isLocal: Boolean
): PropertySymbols {
val property = prepareProperty(firPropertySymbol.fir)
getCachedIrPropertySymbols(property, fakeOverrideOwnerLookupTag)?.let { return it }
return createAndCacheIrPropertySymbols(property, fakeOverrideOwnerLookupTag, isLocal)
}
private fun createAndCacheIrPropertySymbols(
property: FirProperty,
fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag?,
isLocal: Boolean
): PropertySymbols {
val signature = runIf(!isLocal && configuration.linkViaSignatures) {
signatureComposer.composeSignature(property, fakeOverrideOwnerLookupTag)
}
val symbols = createPropertySymbols(signature, property, fakeOverrideOwnerLookupTag)
val irParent = findIrParent(property, fakeOverrideOwnerLookupTag)
if (irParent?.isExternalParent() == true) {
callablesGenerator.createIrProperty(
property,
irParent,
symbols,
predefinedOrigin = property.computeExternalOrigin(),
allowLazyDeclarationsCreation = true
).also {
check(it is Fir2IrLazyProperty)
}
}
cacheIrPropertySymbols(property, symbols, fakeOverrideOwnerLookupTag)
return symbols
} }
fun getCachedIrPropertySymbol( fun getCachedIrPropertySymbol(
@@ -653,6 +657,20 @@ class Fir2IrDeclarationStorage(
} }
} }
private fun getCachedIrPropertySymbols(
property: FirProperty,
fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag?,
signatureCalculator: () -> IdSignature? = { signatureComposer.composeSignature(property, fakeOverrideOwnerLookupTag) }
): PropertySymbols? {
val propertySymbol = getCachedIrPropertySymbol(property, fakeOverrideOwnerLookupTag, signatureCalculator) ?: return null
return PropertySymbols(
propertySymbol,
findGetterOfProperty(propertySymbol)!!,
findSetterOfProperty(propertySymbol),
findBackingFieldOfProperty(propertySymbol)
)
}
fun findGetterOfProperty(propertySymbol: IrPropertySymbol): IrSimpleFunctionSymbol? { fun findGetterOfProperty(propertySymbol: IrPropertySymbol): IrSimpleFunctionSymbol? {
return getterForPropertyCache[propertySymbol] return getterForPropertyCache[propertySymbol]
} }
@@ -741,7 +759,7 @@ class Fir2IrDeclarationStorage(
propertyCache[fir]?.ownerIfBound()?.let { return it.backingField!!.symbol } propertyCache[fir]?.ownerIfBound()?.let { return it.backingField!!.symbol }
val irParent = findIrParent(fir, fakeOverrideOwnerLookupTag = null) val irParent = findIrParent(fir, fakeOverrideOwnerLookupTag = null)
val parentOrigin = (irParent as? IrDeclaration)?.origin ?: IrDeclarationOrigin.DEFINED val parentOrigin = (irParent as? IrDeclaration)?.origin ?: IrDeclarationOrigin.DEFINED
createAndCacheIrProperty(fir, irParent, predefinedOrigin = parentOrigin).backingField!!.symbol createAndCacheIrProperty(fir, irParent, predefinedOrigin = parentOrigin, isLocal = false).backingField!!.symbol
} }
else -> { else -> {
getIrVariableSymbol(fir) getIrVariableSymbol(fir)
@@ -753,32 +771,20 @@ class Fir2IrDeclarationStorage(
return fieldCache[field] return fieldCache[field]
} }
fun recordDelegateFieldMappedToBackingField(field: FirField, irFieldSymbol: IrFieldSymbol) {
fieldCache[field] = irFieldSymbol
}
fun getCachedIrFieldStaticFakeOverrideSymbolByDeclaration(field: FirField): IrFieldSymbol? { fun getCachedIrFieldStaticFakeOverrideSymbolByDeclaration(field: FirField): IrFieldSymbol? {
val ownerLookupTag = field.containingClassLookupTag() ?: return null val ownerLookupTag = field.containingClassLookupTag() ?: return null
return fieldStaticOverrideCache[FieldStaticOverrideKey(ownerLookupTag, field.name)] return fieldStaticOverrideCache[FieldStaticOverrideKey(ownerLookupTag, field.name)]
} }
internal fun getOrCreateDelegateIrField(field: FirField, owner: FirClass, irClass: IrClass): IrField { internal fun createDelegateIrField(field: FirField, irClass: IrClass): IrField {
val initializer = field.initializer
if (initializer is FirQualifiedAccessExpression && initializer.explicitReceiver == null) {
val resolvedSymbol = initializer.calleeReference.toResolvedValueParameterSymbol()
if (resolvedSymbol is FirValueParameterSymbol) {
val name = resolvedSymbol.name
val constructorProperty = owner.declarations.filterIsInstance<FirProperty>().find {
it.name == name && it.source?.kind is KtFakeSourceElementKind.PropertyFromParameter
}
if (constructorProperty != null) {
val irProperty = getOrCreateIrProperty(constructorProperty, irClass)
val backingField = irProperty.backingField!!
fieldCache[field] = backingField.symbol
return backingField
}
}
}
return createAndCacheIrField( return createAndCacheIrField(
field, field,
irParent = irClass, irParent = irClass,
type = initializer?.resolvedType ?: field.returnTypeRef.coneType, type = field.initializer?.resolvedType ?: field.returnTypeRef.coneType,
origin = IrDeclarationOrigin.DELEGATE origin = IrDeclarationOrigin.DELEGATE
) )
} }
@@ -14,9 +14,12 @@ import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.declarations.IrTypeParametersContainer
import org.jetbrains.kotlin.ir.linkage.IrProvider import org.jetbrains.kotlin.ir.linkage.IrProvider
import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.ir.util.IdSignature import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
@@ -177,8 +180,7 @@ class FirIrProvider(val components: Fir2IrComponents) : IrProvider {
shouldNotBeCalled() shouldNotBeCalled()
} }
SymbolKind.PROPERTY_SYMBOL -> { SymbolKind.PROPERTY_SYMBOL -> {
val firProperty = firDeclaration as FirProperty shouldNotBeCalled()
declarationStorage.getOrCreateIrProperty(firProperty, parent)
} }
SymbolKind.FIELD_SYMBOL -> { SymbolKind.FIELD_SYMBOL -> {
val firField = firDeclaration as FirField val firField = firDeclaration as FirField
@@ -11,13 +11,11 @@ import org.jetbrains.kotlin.builtins.UnsignedType
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.containingClassLookupTag
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.fir.scopes.getFunctions import org.jetbrains.kotlin.fir.scopes.getFunctions
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
@@ -705,16 +703,7 @@ class IrBuiltInsOverFir(
private fun findProperty(propertySymbol: FirPropertySymbol): IrPropertySymbol { private fun findProperty(propertySymbol: FirPropertySymbol): IrPropertySymbol {
propertySymbol.lazyResolveToPhase(FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE) propertySymbol.lazyResolveToPhase(FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE)
return components.declarationStorage.getIrPropertySymbol(propertySymbol) as IrPropertySymbol
val irParent = findIrParent(propertySymbol)
return components.declarationStorage.getOrCreateIrProperty(propertySymbol.fir, irParent).symbol
}
private fun findIrParent(firSymbol: FirCallableSymbol<*>): IrDeclarationParent? {
return when (val containingClassLookupTag = firSymbol.containingClassLookupTag()) {
null -> components.declarationStorage.getIrExternalPackageFragment(firSymbol.callableId.packageName, firSymbol.moduleData)
else -> components.classifierStorage.findIrClass(containingClassLookupTag)
}
} }
private val IrClassSymbol.defaultTypeWithoutArguments: IrSimpleType private val IrClassSymbol.defaultTypeWithoutArguments: IrSimpleType
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.backend.* import org.jetbrains.kotlin.fir.backend.*
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.modality import org.jetbrains.kotlin.fir.declarations.utils.modality
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.isLocalClassOrAnonymousObject
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.scope import org.jetbrains.kotlin.fir.resolve.scope
import org.jetbrains.kotlin.fir.scopes.* import org.jetbrains.kotlin.fir.scopes.*
@@ -27,8 +28,10 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.UnsafeDuringIrConstructionAPI import org.jetbrains.kotlin.ir.symbols.UnsafeDuringIrConstructionAPI
import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.classifierOrNull
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.isNullable
import org.jetbrains.kotlin.ir.types.isSubtypeOfClass
import org.jetbrains.kotlin.ir.util.SYNTHETIC_OFFSET import org.jetbrains.kotlin.ir.util.SYNTHETIC_OFFSET
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
@@ -94,6 +97,13 @@ class DelegatedMemberGenerator(private val components: Fir2IrComponents) : Fir2I
bodiesInfo.clear() bodiesInfo.clear()
} }
fun generateWithBodiesIfNeeded(firField: FirField, irField: IrField, firSubClass: FirClass, subClass: IrClass) {
delegatedMemberGenerator.generate(irField, firField, firSubClass, subClass)
if (firSubClass.isLocalClassOrAnonymousObject()) {
delegatedMemberGenerator.generateBodies()
}
}
// Generate delegated members for [subClass]. The synthetic field [irField] has the super interface type. // Generate delegated members for [subClass]. The synthetic field [irField] has the super interface type.
fun generate(irField: IrField, firField: FirField, firSubClass: FirClass, subClass: IrClass) { fun generate(irField: IrField, firField: FirField, firSubClass: FirClass, subClass: IrClass) {
val subClassScope = firSubClass.unsubstitutedScope() val subClassScope = firSubClass.unsubstitutedScope()
@@ -345,7 +355,7 @@ class DelegatedMemberGenerator(private val components: Fir2IrComponents) : Fir2I
firSubClass: FirClass, firSubClass: FirClass,
firDelegateProperty: FirProperty firDelegateProperty: FirProperty
): IrProperty { ): IrProperty {
val delegateProperty = declarationStorage.getOrCreateIrProperty( val delegateProperty = declarationStorage.createAndCacheIrProperty(
firDelegateProperty, subClass, predefinedOrigin = IrDeclarationOrigin.DELEGATED_MEMBER, firDelegateProperty, subClass, predefinedOrigin = IrDeclarationOrigin.DELEGATED_MEMBER,
fakeOverrideOwnerLookupTag = firSubClass.symbol.toLookupTag() fakeOverrideOwnerLookupTag = firSubClass.symbol.toLookupTag()
) )
@@ -8,7 +8,10 @@ package org.jetbrains.kotlin.fir.backend.generators
import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.backend.* import org.jetbrains.kotlin.fir.backend.*
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.* import org.jetbrains.kotlin.fir.declarations.utils.allowsToHaveFakeOverride
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
import org.jetbrains.kotlin.fir.declarations.utils.isStatic
import org.jetbrains.kotlin.fir.resolve.defaultType import org.jetbrains.kotlin.fir.resolve.defaultType
import org.jetbrains.kotlin.fir.resolve.isRealOwnerOf import org.jetbrains.kotlin.fir.resolve.isRealOwnerOf
import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolve.toSymbol
@@ -16,7 +19,10 @@ import org.jetbrains.kotlin.fir.scopes.*
import org.jetbrains.kotlin.fir.scopes.impl.FirFakeOverrideGenerator import org.jetbrains.kotlin.fir.scopes.impl.FirFakeOverrideGenerator
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirFieldSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.types.coneType import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.*
@@ -129,11 +135,18 @@ class FakeOverrideGenerator(
useSiteOrStaticScope.processPropertiesByName(name) { propertyOrFieldSymbol -> useSiteOrStaticScope.processPropertiesByName(name) { propertyOrFieldSymbol ->
when (propertyOrFieldSymbol) { when (propertyOrFieldSymbol) {
is FirPropertySymbol -> { is FirPropertySymbol -> {
@OptIn(LeakedDeclarationCaches::class)
createFakeOverriddenIfNeeded( createFakeOverriddenIfNeeded(
firClass, irClass, isLocal, propertyOrFieldSymbol, firClass, irClass, isLocal, propertyOrFieldSymbol,
declarationStorage::getCachedIrPropertySymbol, declarationStorage::getCachedIrPropertySymbol,
declarationStorage::createAndCacheIrProperty, { property, irParent, predefinedOrigin, isLocal ->
declarationStorage.createAndCacheIrProperty(
property,
irParent,
predefinedOrigin,
isLocal,
allowLazyDeclarationsCreation = true
)
},
createFakeOverrideSymbol = { firProperty, callableSymbol -> createFakeOverrideSymbol = { firProperty, callableSymbol ->
val symbolForOverride = val symbolForOverride =
FirFakeOverrideGenerator.createSymbolForSubstitutionOverride(callableSymbol, firClass.symbol.classId) FirFakeOverrideGenerator.createSymbolForSubstitutionOverride(callableSymbol, firClass.symbol.classId)
@@ -538,7 +551,6 @@ class FakeOverrideGenerator(
} }
context(Fir2IrComponents) context(Fir2IrComponents)
@OptIn(UnsafeDuringIrConstructionAPI::class)
internal fun FirProperty.generateOverriddenAccessorSymbols(containingClass: FirClass, isGetter: Boolean): List<IrSimpleFunctionSymbol> { internal fun FirProperty.generateOverriddenAccessorSymbols(containingClass: FirClass, isGetter: Boolean): List<IrSimpleFunctionSymbol> {
val scope = containingClass.unsubstitutedScope() val scope = containingClass.unsubstitutedScope()
scope.processPropertiesByName(name) {} scope.processPropertiesByName(name) {}
@@ -555,8 +567,8 @@ internal fun FirProperty.generateOverriddenAccessorSymbols(containingClass: FirC
for (overriddenIrPropertySymbol in fakeOverrideGenerator.getOverriddenSymbolsInSupertypes(overriddenSymbol, superClasses)) { for (overriddenIrPropertySymbol in fakeOverrideGenerator.getOverriddenSymbolsInSupertypes(overriddenSymbol, superClasses)) {
val overriddenIrAccessorSymbol = val overriddenIrAccessorSymbol =
if (isGetter) overriddenIrPropertySymbol.owner.getter?.symbol if (isGetter) declarationStorage.findGetterOfProperty(overriddenIrPropertySymbol)
else overriddenIrPropertySymbol.owner.setter?.symbol else declarationStorage.findSetterOfProperty(overriddenIrPropertySymbol)
if (overriddenIrAccessorSymbol != null) { if (overriddenIrAccessorSymbol != null) {
assert(overriddenIrAccessorSymbol != symbol) { "Cannot add property $overriddenIrAccessorSymbol to its own overriddenSymbols" } assert(overriddenIrAccessorSymbol != symbol) { "Cannot add property $overriddenIrAccessorSymbol to its own overriddenSymbols" }
overriddenSet += overriddenIrAccessorSymbol overriddenSet += overriddenIrAccessorSymbol
@@ -26,7 +26,6 @@ import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyConstructor
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyProperty import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyProperty
import org.jetbrains.kotlin.fir.references.toResolvedBaseSymbol import org.jetbrains.kotlin.fir.references.toResolvedBaseSymbol
import org.jetbrains.kotlin.fir.resolve.calls.FirSimpleSyntheticPropertySymbol import org.jetbrains.kotlin.fir.resolve.calls.FirSimpleSyntheticPropertySymbol
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.isLocalClassOrAnonymousObject
import org.jetbrains.kotlin.fir.resolve.isKFunctionInvoke import org.jetbrains.kotlin.fir.resolve.isKFunctionInvoke
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
@@ -51,7 +50,6 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.NameUtils import org.jetbrains.kotlin.name.NameUtils
import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.types.AbstractTypeChecker import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.utils.addToStdlib.runUnless
import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment
import kotlin.contracts.ExperimentalContracts import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.contract import kotlin.contracts.contract
@@ -228,8 +226,8 @@ class Fir2IrCallableDeclarationsGenerator(val components: Fir2IrComponents) : Fi
irParent: IrDeclarationParent?, irParent: IrDeclarationParent?,
symbols: PropertySymbols, symbols: PropertySymbols,
predefinedOrigin: IrDeclarationOrigin? = null, predefinedOrigin: IrDeclarationOrigin? = null,
isLocal: Boolean = false,
fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag? = null, fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag? = null,
allowLazyDeclarationsCreation: Boolean
): IrProperty = convertCatching(property) { ): IrProperty = convertCatching(property) {
val origin = when { val origin = when {
!predefinedOrigin.isExternal && !predefinedOrigin.isExternal &&
@@ -245,16 +243,12 @@ class Fir2IrCallableDeclarationsGenerator(val components: Fir2IrComponents) : Fi
} }
// See similar comments in createIrFunction above // See similar comments in createIrFunction above
val parentIsExternal = irParent.isExternalParent() val parentIsExternal = irParent.isExternalParent()
val signature = if (parentIsExternal) {
runUnless( if (!allowLazyDeclarationsCreation) {
isLocal || error("Lazy properties should be processed in Fir2IrDeclarationStorage")
!configuration.linkViaSignatures && !parentIsExternal &&
property.dispatchReceiverType?.isPrimitive != true && property.containerSource == null &&
origin != IrDeclarationOrigin.FAKE_OVERRIDE && !property.isOverride
) {
signatureComposer.composeSignature(property, fakeOverrideOwnerLookupTag)
} }
if (parentIsExternal && signature != null) { @OptIn(UnsafeDuringIrConstructionAPI::class)
if (symbols.propertySymbol.isBound) return symbols.propertySymbol.owner
// For private functions signature is null, fallback to non-lazy property // For private functions signature is null, fallback to non-lazy property
return lazyDeclarationsGenerator.createIrLazyProperty(property, irParent!!, symbols, origin) return lazyDeclarationsGenerator.createIrLazyProperty(property, irParent!!, symbols, origin)
} }
@@ -532,18 +526,6 @@ class Fir2IrCallableDeclarationsGenerator(val components: Fir2IrComponents) : Fi
else -> Visibilities.Private else -> Visibilities.Private
} }
fun createIrFieldAndDelegatedMembers(field: FirField, owner: FirClass, irClass: IrClass): IrField? {
// Either take a corresponding constructor property backing field,
// or create a separate delegate field
val irField = declarationStorage.getOrCreateDelegateIrField(field, owner, irClass)
delegatedMemberGenerator.generate(irField, field, owner, irClass)
if (owner.isLocalClassOrAnonymousObject()) {
delegatedMemberGenerator.generateBodies()
}
// If it's a property backing field, it should not be added to the class in Fir2IrConverter, so it's not returned
return irField.takeIf { it.correspondingPropertySymbol == null }
}
internal fun createIrField( internal fun createIrField(
field: FirField, field: FirField,
irParent: IrDeclarationParent?, irParent: IrDeclarationParent?,
@@ -5,13 +5,13 @@
package org.jetbrains.kotlin.fir.backend.generators package org.jetbrains.kotlin.fir.backend.generators
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.backend.* import org.jetbrains.kotlin.fir.backend.*
import org.jetbrains.kotlin.fir.backend.convertWithOffsets import org.jetbrains.kotlin.fir.containingClassLookupTag
import org.jetbrains.kotlin.fir.backend.isStubPropertyForPureField
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.isSubstitutionOrIntersectionOverride
import org.jetbrains.kotlin.fir.lazy.* import org.jetbrains.kotlin.fir.lazy.*
import org.jetbrains.kotlin.fir.resolve.providers.firProvider import org.jetbrains.kotlin.fir.resolve.providers.firProvider
import org.jetbrains.kotlin.fir.unwrapUseSiteSubstitutionOverrides
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
@@ -214,7 +214,9 @@ class Fir2IrLazyClass(
symbol.containingClassLookupTag() != ownerLookupTag -> {} symbol.containingClassLookupTag() != ownerLookupTag -> {}
symbol !is FirPropertySymbol -> {} symbol !is FirPropertySymbol -> {}
else -> { else -> {
result += declarationStorage.getOrCreateIrProperty(symbol.fir, this, origin) // Lazy declarations are created together with their symbol, so it's safe to take the owner here
@OptIn(UnsafeDuringIrConstructionAPI::class)
result += declarationStorage.getIrPropertySymbol(symbol, lookupTag).owner as IrProperty
} }
} }
} }
@@ -109,70 +109,67 @@ class Fir2IrLazyProperty(
} }
} }
override var backingField: IrField? by lazyVar(lock) { override var backingField: IrField? = when {
when { fir.hasExplicitBackingField -> {
fir.hasExplicitBackingField -> { val backingFieldType = with(typeConverter) {
val backingFieldType = with(typeConverter) { fir.backingField?.returnTypeRef?.toIrType()
fir.backingField?.returnTypeRef?.toIrType()
}
val initializer = fir.backingField?.initializer ?: fir.initializer
val visibility = fir.backingField?.visibility ?: fir.visibility
callablesGenerator.createBackingField(
this@Fir2IrLazyProperty,
fir,
IrDeclarationOrigin.PROPERTY_BACKING_FIELD,
symbols.backingFieldSymbol!!,
components.visibilityConverter.convertToDescriptorVisibility(visibility),
fir.name,
fir.isVal,
initializer,
backingFieldType
).also { field ->
field.initializer = toIrInitializer(initializer)
}
} }
extensions.hasBackingField(fir, session) && origin != IrDeclarationOrigin.FAKE_OVERRIDE -> { val initializer = fir.backingField?.initializer ?: fir.initializer
callablesGenerator.createBackingField( val visibility = fir.backingField?.visibility ?: fir.visibility
this@Fir2IrLazyProperty, callablesGenerator.createBackingField(
fir, this@Fir2IrLazyProperty,
IrDeclarationOrigin.PROPERTY_BACKING_FIELD, fir,
symbols.backingFieldSymbol!!, IrDeclarationOrigin.PROPERTY_BACKING_FIELD,
components.visibilityConverter.convertToDescriptorVisibility(fir.visibility), symbols.backingFieldSymbol!!,
fir.name, components.visibilityConverter.convertToDescriptorVisibility(visibility),
fir.isVal, fir.name,
fir.initializer, fir.isVal,
type initializer,
).also { field -> backingFieldType
field.initializer = toIrInitializer(fir.initializer) ).also { field ->
} field.initializer = toIrInitializer(initializer)
} }
fir.delegate != null -> {
callablesGenerator.createBackingField(
this@Fir2IrLazyProperty,
fir,
IrDeclarationOrigin.PROPERTY_DELEGATE,
symbols.backingFieldSymbol!!,
components.visibilityConverter.convertToDescriptorVisibility(fir.visibility),
NameUtils.propertyDelegateName(fir.name),
true,
fir.delegate
)
}
else -> {
null
}
}?.apply {
this.parent = this@Fir2IrLazyProperty.parent
this.annotations = fir.backingField?.annotations?.mapNotNull {
callGenerator.convertToIrConstructorCall(it) as? IrConstructorCall
}.orEmpty()
} }
extensions.hasBackingField(fir, session) && origin != IrDeclarationOrigin.FAKE_OVERRIDE -> {
callablesGenerator.createBackingField(
this@Fir2IrLazyProperty,
fir,
IrDeclarationOrigin.PROPERTY_BACKING_FIELD,
symbols.backingFieldSymbol!!,
components.visibilityConverter.convertToDescriptorVisibility(fir.visibility),
fir.name,
fir.isVal,
fir.initializer,
type
).also { field ->
field.initializer = toIrInitializer(fir.initializer)
}
}
fir.delegate != null -> {
callablesGenerator.createBackingField(
this@Fir2IrLazyProperty,
fir,
IrDeclarationOrigin.PROPERTY_DELEGATE,
symbols.backingFieldSymbol!!,
components.visibilityConverter.convertToDescriptorVisibility(fir.visibility),
NameUtils.propertyDelegateName(fir.name),
true,
fir.delegate
)
}
else -> {
null
}
}?.apply {
this.parent = this@Fir2IrLazyProperty.parent
this.annotations = fir.backingField?.annotations?.mapNotNull {
callGenerator.convertToIrConstructorCall(it) as? IrConstructorCall
}.orEmpty()
} }
override var getter: IrSimpleFunction? by lazyVar(lock) { override var getter: IrSimpleFunction? = Fir2IrLazyPropertyAccessor(
Fir2IrLazyPropertyAccessor( components, startOffset, endOffset,
components, startOffset, endOffset, origin =when {
origin = when {
origin == IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB -> origin origin == IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB -> origin
fir.delegate != null -> IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR fir.delegate != null -> IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR
origin == IrDeclarationOrigin.FAKE_OVERRIDE -> origin origin == IrDeclarationOrigin.FAKE_OVERRIDE -> origin
@@ -185,16 +182,15 @@ class Fir2IrLazyProperty(
firParentProperty = fir, firParentProperty = fir,
firParentClass = containingClass, firParentClass = containingClass,
symbol = symbols.getterSymbol, symbol = symbols.getterSymbol,
parent = this@Fir2IrLazyProperty.parent, parent = this@Fir2IrLazyProperty.parent,
isFakeOverride = isFakeOverride, isFakeOverride = isFakeOverride,
correspondingPropertySymbol = this.symbol correspondingPropertySymbol = this.symbol
).apply { ).apply {
classifiersGenerator.setTypeParameters(this, this@Fir2IrLazyProperty.fir, ConversionTypeOrigin.DEFAULT) classifiersGenerator.setTypeParameters(this, this@Fir2IrLazyProperty.fir, ConversionTypeOrigin.DEFAULT)
}
} }
override var setter: IrSimpleFunction? by lazyVar(lock) { override var setter: IrSimpleFunction? = run {
if (!fir.isVar) return@lazyVar null if (!fir.isVar) return@run null
Fir2IrLazyPropertyAccessor( Fir2IrLazyPropertyAccessor(
components, startOffset, endOffset, components, startOffset, endOffset,
origin = when { origin = when {