[FIR2IR] Manage property symbols in declaration storage instead of declaration generator

This is needed to be able to implement creation of unbound symbols
  for references of corresponding declarations (KT-62856)
This commit is contained in:
Dmitriy Novozhilov
2023-11-03 14:52:45 +02:00
committed by Space Team
parent fe66f3a384
commit aadc9ce6d5
4 changed files with 329 additions and 338 deletions
@@ -13,9 +13,7 @@ import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.buildProperty
import org.jetbrains.kotlin.fir.declarations.synthetic.FirSyntheticProperty
import org.jetbrains.kotlin.fir.declarations.utils.isStatic
import org.jetbrains.kotlin.fir.declarations.utils.nameOrSpecialName
import org.jetbrains.kotlin.fir.declarations.utils.visibility
import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.descriptors.FirBuiltInsPackageFragment
import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
@@ -27,19 +25,14 @@ import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.*
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.fir.types.*
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.declarations.UNDEFINED_PARAMETER_INDEX
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl
import org.jetbrains.kotlin.ir.expressions.IrSyntheticBodyKind
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.*
import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.ir.util.classId
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
@@ -543,11 +536,54 @@ class Fir2IrDeclarationStorage(
): IrProperty {
@Suppress("NAME_SHADOWING")
val property = prepareProperty(property)
val irProperty = callablesGenerator.createIrProperty(property, irParent, predefinedOrigin, isLocal, fakeOverrideOwnerLookupTag)
val signature = runIf(!isLocal && configuration.linkViaSignatures) {
signatureComposer.composeSignature(property, fakeOverrideOwnerLookupTag)
}
val symbols = createPropertySymbols(signature, property, fakeOverrideOwnerLookupTag)
val irProperty = callablesGenerator.createIrProperty(
property, irParent, symbols, predefinedOrigin, isLocal, fakeOverrideOwnerLookupTag
)
cacheIrProperty(property, irProperty, fakeOverrideOwnerLookupTag)
return irProperty
}
private fun createPropertySymbols(
signature: IdSignature?,
property: FirProperty,
fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag?,
): PropertySymbols {
val propertySymbol = when {
signature != null -> when (property.isStubPropertyForPureField) {
// Very special case when two similar properties can exist so conflicts in SymbolTable are possible.
// See javaCloseFieldAndKotlinProperty.kt in BB tests
true -> IrPropertyPublicSymbolImpl(signature).also {
symbolTable.declarePropertyWithSignature(signature, it)
}
else -> symbolTable.referenceProperty(signature)
}
else -> IrPropertySymbolImpl()
}
val getterSignature = runIf(signature != null) {
signatureComposer.composeAccessorSignature(property, isSetter = false, fakeOverrideOwnerLookupTag)
}
val getterSymbol = createFunctionSymbol(getterSignature)
val setterSymbol = runIf(property.isVar) {
val setterSignature = runIf(signature != null) {
signatureComposer.composeAccessorSignature(property, isSetter = true, fakeOverrideOwnerLookupTag)
}
createFunctionSymbol(setterSignature)
}
val backingFieldSymbol = runIf(property.delegate != null || property.hasBackingField) {
createFieldSymbol()
}
return PropertySymbols(propertySymbol, getterSymbol, setterSymbol, backingFieldSymbol)
}
private fun cacheIrProperty(
property: FirProperty,
irProperty: IrProperty,
@@ -773,6 +809,10 @@ class Fir2IrDeclarationStorage(
return irField
}
private fun createFieldSymbol(): IrFieldSymbol {
return IrFieldSymbolImpl()
}
// This function returns null if this field/ownerClassId combination does not describe static fake override
private fun getFieldStaticFakeOverrideKey(field: FirField, ownerLookupTag: ConeClassLikeLookupTag?): FieldStaticOverrideKey? {
if (ownerLookupTag == null || !field.isStatic ||
@@ -825,7 +865,8 @@ class Fir2IrDeclarationStorage(
property: FirProperty,
irParent: IrDeclarationParent
): IrLocalDelegatedProperty {
val irProperty = callablesGenerator.createIrLocalDelegatedProperty(property, irParent)
val symbols = createLocalDelegatedPropertySymbols(property)
val irProperty = callablesGenerator.createIrLocalDelegatedProperty(property, irParent, symbols)
val symbol = irProperty.symbol
delegateVariableForPropertyCache[symbol] = irProperty.delegate.symbol
getterForPropertyCache[symbol] = irProperty.getter.symbol
@@ -834,6 +875,15 @@ class Fir2IrDeclarationStorage(
return irProperty
}
private fun createLocalDelegatedPropertySymbols(property: FirProperty): LocalDelegatedPropertySymbols {
val propertySymbol = IrLocalDelegatedPropertySymbolImpl()
val getterSymbol = createFunctionSymbol(signature = null)
val setterSymbol = runIf(property.isVar) {
createFunctionSymbol(signature = null)
}
return LocalDelegatedPropertySymbols(propertySymbol, getterSymbol, setterSymbol)
}
// ------------------------------------ variables ------------------------------------
fun createAndCacheIrVariable(
@@ -1244,3 +1294,16 @@ annotation class GetOrCreateSensitiveAPI
internal fun <D : IrDeclaration> IrBindableSymbol<*, D>.ownerIfBound(): D? {
return runIf(isBound) { owner }
}
data class PropertySymbols(
val propertySymbol: IrPropertySymbol,
val getterSymbol: IrSimpleFunctionSymbol,
val setterSymbol: IrSimpleFunctionSymbol?,
val backingFieldSymbol: IrFieldSymbol?,
)
data class LocalDelegatedPropertySymbols(
val propertySymbol: IrLocalDelegatedPropertySymbol,
val getterSymbol: IrSimpleFunctionSymbol,
val setterSymbol: IrSimpleFunctionSymbol?,
)
@@ -70,17 +70,6 @@ class Fir2IrCallableDeclarationsGenerator(val components: Fir2IrComponents) : Fi
// ------------------------------------ functions ------------------------------------
internal fun declareIrSimpleFunction(
signature: IdSignature?,
factory: (IrSimpleFunctionSymbol) -> IrSimpleFunction
): IrSimpleFunction {
return if (signature == null) {
factory(IrSimpleFunctionSymbolImpl())
} else {
symbolTable.declareSimpleFunction(signature, { IrSimpleFunctionPublicSymbolImpl(signature) }, factory)
}
}
fun createIrFunction(
function: FirFunction,
irParent: IrDeclarationParent?,
@@ -228,19 +217,10 @@ class Fir2IrCallableDeclarationsGenerator(val components: Fir2IrComponents) : Fi
// ------------------------------------ properties ------------------------------------
private fun declareIrProperty(
signature: IdSignature?,
factory: (IrPropertySymbol) -> IrProperty
): IrProperty {
return if (signature == null)
factory(IrPropertySymbolImpl())
else
symbolTable.declareProperty(signature, { IrPropertyPublicSymbolImpl(signature) }, factory)
}
fun createIrProperty(
property: FirProperty,
irParent: IrDeclarationParent?,
symbols: PropertySymbols,
predefinedOrigin: IrDeclarationOrigin? = null,
isLocal: Boolean = false,
fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag? = null,
@@ -270,118 +250,115 @@ class Fir2IrCallableDeclarationsGenerator(val components: Fir2IrComponents) : Fi
}
if (parentIsExternal && signature != null) {
// For private functions signature is null, fallback to non-lazy property
return lazyDeclarationsGenerator.createIrLazyProperty(property, signature, irParent!!, origin)
return lazyDeclarationsGenerator.createIrLazyProperty(property, irParent!!, symbols, origin)
}
return property.convertWithOffsets { startOffset, endOffset ->
val result = declareIrProperty(signature) { symbol ->
classifierStorage.preCacheTypeParameters(property, symbol)
irFactory.createProperty(
startOffset = startOffset,
endOffset = endOffset,
origin = origin,
name = property.name,
visibility = components.visibilityConverter.convertToDescriptorVisibility(property.visibility),
modality = property.modality!!,
symbol = symbol,
isVar = property.isVar,
isConst = property.isConst,
isLateinit = property.isLateInit,
isDelegated = property.delegate != null,
isExternal = property.isExternal,
containerSource = property.containerSource,
isExpect = property.isExpect,
).apply {
metadata = FirMetadataSource.Property(property)
convertAnnotationsForNonDeclaredMembers(property, origin)
declarationStorage.withScope(symbol) {
// IrProperty is never created for local variables
setParent(irParent)
addDeclarationToParent(this, irParent)
val type = property.returnTypeRef.toIrType()
val delegate = property.delegate
val getter = property.getter
val setter = property.setter
if (delegate != null || property.hasBackingField) {
val backingField = if (delegate != null) {
((delegate as? FirQualifiedAccessExpression)?.calleeReference?.toResolvedBaseSymbol()?.fir as? FirTypeParameterRefsOwner)?.let {
classifierStorage.preCacheTypeParameters(it, symbol)
}
createBackingField(
this,
property,
IrDeclarationOrigin.PROPERTY_DELEGATE,
components.visibilityConverter.convertToDescriptorVisibility(property.fieldVisibility),
NameUtils.propertyDelegateName(property.name),
true,
delegate
)
} else {
val initializer = getEffectivePropertyInitializer(property, resolveIfNeeded = true)
// There are cases when we get here for properties
// that have no backing field. For example, in the
// funExpression.kt test there's an attempt
// to access the `javaClass` property of the `foo0`'s
// `block` argument
val typeToUse = property.backingField?.returnTypeRef?.toIrType() ?: type
createBackingField(
this,
property,
IrDeclarationOrigin.PROPERTY_BACKING_FIELD,
components.visibilityConverter.convertToDescriptorVisibility(property.fieldVisibility),
property.name,
property.isVal,
initializer,
typeToUse
).also { field ->
if (initializer is FirConstExpression<*>) {
val constType = initializer.resolvedType.toIrType()
field.initializer = factory.createExpressionBody(initializer.toIrConst(constType))
}
classifierStorage.preCacheTypeParameters(property, symbols.propertySymbol)
irFactory.createProperty(
startOffset = startOffset,
endOffset = endOffset,
origin = origin,
name = property.name,
visibility = components.visibilityConverter.convertToDescriptorVisibility(property.visibility),
modality = property.modality!!,
symbol = symbols.propertySymbol,
isVar = property.isVar,
isConst = property.isConst,
isLateinit = property.isLateInit,
isDelegated = property.delegate != null,
isExternal = property.isExternal,
containerSource = property.containerSource,
isExpect = property.isExpect,
).apply {
metadata = FirMetadataSource.Property(property)
convertAnnotationsForNonDeclaredMembers(property, origin)
declarationStorage.withScope(symbol) {
// IrProperty is never created for local variables
setParent(irParent)
addDeclarationToParent(this, irParent)
val type = property.returnTypeRef.toIrType()
val delegate = property.delegate
val getter = property.getter
val setter = property.setter
if (delegate != null || property.hasBackingField) {
val backingField = if (delegate != null) {
((delegate as? FirQualifiedAccessExpression)?.calleeReference?.toResolvedBaseSymbol()?.fir as? FirTypeParameterRefsOwner)?.let {
classifierStorage.preCacheTypeParameters(it, symbol)
}
createBackingField(
this,
property,
IrDeclarationOrigin.PROPERTY_DELEGATE,
symbols.backingFieldSymbol!!,
components.visibilityConverter.convertToDescriptorVisibility(property.fieldVisibility),
NameUtils.propertyDelegateName(property.name),
true,
delegate
)
} else {
val initializer = getEffectivePropertyInitializer(property, resolveIfNeeded = true)
// There are cases when we get here for properties
// that have no backing field. For example, in the
// funExpression.kt test there's an attempt
// to access the `javaClass` property of the `foo0`'s
// `block` argument
val typeToUse = property.backingField?.returnTypeRef?.toIrType() ?: type
createBackingField(
this,
property,
IrDeclarationOrigin.PROPERTY_BACKING_FIELD,
symbols.backingFieldSymbol!!,
components.visibilityConverter.convertToDescriptorVisibility(property.fieldVisibility),
property.name,
property.isVal,
initializer,
typeToUse
).also { field ->
if (initializer is FirConstExpression<*>) {
val constType = initializer.resolvedType.toIrType()
field.initializer = factory.createExpressionBody(initializer.toIrConst(constType))
}
}
this.backingField = backingField
}
if (irParent != null) {
backingField?.parent = irParent
}
this.getter = getter.convertWithOffsets(startOffset, endOffset) { startOffset, endOffset ->
this.backingField = backingField
}
if (irParent != null) {
backingField?.parent = irParent
}
this.getter = getter.convertWithOffsets(startOffset, endOffset) { startOffset, endOffset ->
createIrPropertyAccessor(
getter, property, this, symbols.getterSymbol, type, irParent, false,
when {
origin == IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB -> origin
origin == IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER -> origin
delegate != null -> IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR
origin == IrDeclarationOrigin.FAKE_OVERRIDE -> origin
origin == IrDeclarationOrigin.DELEGATED_MEMBER -> origin
getter == null || getter is FirDefaultPropertyGetter -> IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR
else -> origin
},
startOffset, endOffset,
property.unwrapFakeOverrides().getter,
)
}
if (property.isVar) {
this.setter = setter.convertWithOffsets(startOffset, endOffset) { startOffset, endOffset ->
createIrPropertyAccessor(
getter, property, this, type, irParent, false,
setter, property, this, symbols.setterSymbol!!, type, irParent, true,
when {
origin == IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB -> origin
origin == IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER -> origin
delegate != null -> IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR
origin == IrDeclarationOrigin.FAKE_OVERRIDE -> origin
origin == IrDeclarationOrigin.DELEGATED_MEMBER -> origin
getter == null || getter is FirDefaultPropertyGetter -> IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR
setter is FirDefaultPropertySetter -> IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR
else -> origin
},
startOffset, endOffset,
dontUseSignature = signature == null, fakeOverrideOwnerLookupTag,
property.unwrapFakeOverrides().getter,
property.unwrapFakeOverrides().setter,
)
}
if (property.isVar) {
this.setter = setter.convertWithOffsets(startOffset, endOffset) { startOffset, endOffset ->
createIrPropertyAccessor(
setter, property, this, type, irParent, true,
when {
delegate != null -> IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR
origin == IrDeclarationOrigin.FAKE_OVERRIDE -> origin
origin == IrDeclarationOrigin.DELEGATED_MEMBER -> origin
setter is FirDefaultPropertySetter -> IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR
else -> origin
},
startOffset, endOffset,
dontUseSignature = signature == null, fakeOverrideOwnerLookupTag,
property.unwrapFakeOverrides().setter,
)
}
}
}
}
}
result
}
}
@@ -439,82 +416,75 @@ class Fir2IrCallableDeclarationsGenerator(val components: Fir2IrComponents) : Fi
propertyAccessor: FirPropertyAccessor?,
property: FirProperty,
correspondingProperty: IrDeclarationWithName,
symbol: IrSimpleFunctionSymbol,
propertyType: IrType,
irParent: IrDeclarationParent?,
isSetter: Boolean,
origin: IrDeclarationOrigin,
startOffset: Int,
endOffset: Int,
dontUseSignature: Boolean = false,
fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag? = null,
propertyAccessorForAnnotations: FirPropertyAccessor? = propertyAccessor,
): IrSimpleFunction = convertCatching(propertyAccessor ?: property) {
val prefix = if (isSetter) "set" else "get"
val signature =
runUnless(dontUseSignature) {
signatureComposer.composeAccessorSignature(property, isSetter, fakeOverrideOwnerLookupTag)
}
val containerSource = (correspondingProperty as? IrProperty)?.containerSource
return declareIrSimpleFunction(signature) { symbol ->
val accessorReturnType = if (isSetter) irBuiltIns.unitType else propertyType
val visibility = propertyAccessor?.visibility?.let {
components.visibilityConverter.convertToDescriptorVisibility(it)
val accessorReturnType = if (isSetter) irBuiltIns.unitType else propertyType
val visibility = propertyAccessor?.visibility?.let {
components.visibilityConverter.convertToDescriptorVisibility(it)
}
return irFactory.createSimpleFunction(
startOffset = startOffset,
endOffset = endOffset,
origin = origin,
name = Name.special("<$prefix-${correspondingProperty.name}>"),
visibility = visibility ?: (correspondingProperty as IrDeclarationWithVisibility).visibility,
isInline = propertyAccessor?.isInline == true,
isExpect = false,
returnType = accessorReturnType,
modality = (correspondingProperty as? IrOverridableMember)?.modality ?: Modality.FINAL,
symbol = symbol,
isTailrec = false,
isSuspend = false,
isOperator = false,
isInfix = false,
isExternal = propertyAccessor?.isExternal == true,
containerSource = containerSource,
).apply {
correspondingPropertySymbol = (correspondingProperty as? IrProperty)?.symbol
if (propertyAccessor != null) {
metadata = FirMetadataSource.Function(propertyAccessor)
// Note that deserialized annotations are stored in the accessor, not the property.
convertAnnotationsForNonDeclaredMembers(propertyAccessor, origin)
}
irFactory.createSimpleFunction(
startOffset = startOffset,
endOffset = endOffset,
origin = origin,
name = Name.special("<$prefix-${correspondingProperty.name}>"),
visibility = visibility ?: (correspondingProperty as IrDeclarationWithVisibility).visibility,
isInline = propertyAccessor?.isInline == true,
isExpect = false,
returnType = accessorReturnType,
modality = (correspondingProperty as? IrOverridableMember)?.modality ?: Modality.FINAL,
symbol = symbol,
isTailrec = false,
isSuspend = false,
isOperator = false,
isInfix = false,
isExternal = propertyAccessor?.isExternal == true,
containerSource = containerSource,
).apply {
correspondingPropertySymbol = (correspondingProperty as? IrProperty)?.symbol
if (propertyAccessor != null) {
metadata = FirMetadataSource.Function(propertyAccessor)
// Note that deserialized annotations are stored in the accessor, not the property.
convertAnnotationsForNonDeclaredMembers(propertyAccessor, origin)
}
if (propertyAccessorForAnnotations != null) {
convertAnnotationsForNonDeclaredMembers(propertyAccessorForAnnotations, origin)
if (propertyAccessorForAnnotations != null) {
convertAnnotationsForNonDeclaredMembers(propertyAccessorForAnnotations, origin)
}
classifiersGenerator.setTypeParameters(
this, property, if (isSetter) ConversionTypeOrigin.SETTER else ConversionTypeOrigin.DEFAULT
)
val dispatchReceiverType = computeDispatchReceiverType(this, property, irParent)
// NB: we should enter accessor' scope before declaring its parameters
// (both setter default and receiver ones, if any)
declarationStorage.withScope(symbol) {
if (propertyAccessor == null && isSetter) {
declareDefaultSetterParameter(
property.returnTypeRef.toIrType(ConversionTypeOrigin.SETTER),
firValueParameter = null
)
}
classifiersGenerator.setTypeParameters(
this, property, if (isSetter) ConversionTypeOrigin.SETTER else ConversionTypeOrigin.DEFAULT
// property accessors does not belong to declarations of class/file, but are referenced via property,
// so there is no need to add accessor to list of parents declarations
setParent(irParent)
declareParameters(
propertyAccessor, irParent, dispatchReceiverType,
isStatic = irParent !is IrClass || propertyAccessor?.isStatic == true, forSetter = isSetter,
parentPropertyReceiver = property.receiverParameter,
)
}
if (correspondingProperty is Fir2IrLazyProperty && correspondingProperty.containingClass != null && !isFakeOverride && dispatchReceiverType != null) {
this.overriddenSymbols = correspondingProperty.fir.generateOverriddenAccessorSymbols(
correspondingProperty.containingClass, !isSetter
)
val dispatchReceiverType = computeDispatchReceiverType(this, property, irParent)
// NB: we should enter accessor' scope before declaring its parameters
// (both setter default and receiver ones, if any)
declarationStorage.withScope(symbol) {
if (propertyAccessor == null && isSetter) {
declareDefaultSetterParameter(
property.returnTypeRef.toIrType(ConversionTypeOrigin.SETTER),
firValueParameter = null
)
}
// property accessors does not belong to declarations of class/file, but are referenced via property,
// so there is no need to add accessor to list of parents declarations
setParent(irParent)
declareParameters(
propertyAccessor, irParent, dispatchReceiverType,
isStatic = irParent !is IrClass || propertyAccessor?.isStatic == true, forSetter = isSetter,
parentPropertyReceiver = property.receiverParameter,
)
}
if (correspondingProperty is Fir2IrLazyProperty && correspondingProperty.containingClass != null && !isFakeOverride && dispatchReceiverType != null) {
this.overriddenSymbols = correspondingProperty.fir.generateOverriddenAccessorSymbols(
correspondingProperty.containingClass, !isSetter
)
}
}
}
}
@@ -525,6 +495,7 @@ class Fir2IrCallableDeclarationsGenerator(val components: Fir2IrComponents) : Fi
irProperty: IrProperty,
firProperty: FirProperty,
origin: IrDeclarationOrigin,
symbol: IrFieldSymbol,
visibility: DescriptorVisibility,
name: Name,
isFinal: Boolean,
@@ -532,25 +503,23 @@ class Fir2IrCallableDeclarationsGenerator(val components: Fir2IrComponents) : Fi
type: IrType? = null
): IrField = convertCatching(firProperty) {
val inferredType = type ?: firInitializerExpression!!.resolvedType.toIrType()
return declareIrField { symbol ->
(firProperty.delegate ?: firProperty.backingField ?: firProperty).convertWithOffsets { startOffset: Int, endOffset: Int ->
irFactory.createField(
startOffset = startOffset,
endOffset = endOffset,
origin = origin,
name = name,
visibility = visibility,
symbol = symbol,
type = inferredType,
isFinal = isFinal,
isStatic = firProperty.isStatic || !(irProperty.parent is IrClass || irProperty.parent is IrScript),
isExternal = firProperty.isExternal,
).also {
it.correspondingPropertySymbol = irProperty.symbol
}.apply {
metadata = FirMetadataSource.Property(firProperty)
convertAnnotationsForNonDeclaredMembers(firProperty, origin)
}
return (firProperty.delegate ?: firProperty.backingField ?: firProperty).convertWithOffsets { startOffset: Int, endOffset: Int ->
irFactory.createField(
startOffset = startOffset,
endOffset = endOffset,
origin = origin,
name = name,
visibility = visibility,
symbol = symbol,
type = inferredType,
isFinal = isFinal,
isStatic = firProperty.isStatic || !(irProperty.parent is IrClass || irProperty.parent is IrScript),
isExternal = firProperty.isExternal,
).also {
it.correspondingPropertySymbol = irProperty.symbol
}.apply {
metadata = FirMetadataSource.Property(firProperty)
convertAnnotationsForNonDeclaredMembers(firProperty, origin)
}
}
}
@@ -565,10 +534,6 @@ class Fir2IrCallableDeclarationsGenerator(val components: Fir2IrComponents) : Fi
else -> Visibilities.Private
}
private fun declareIrField(factory: (IrFieldSymbol) -> IrField): IrField {
return factory(IrFieldSymbolImpl())
}
fun createIrFieldAndDelegatedMembers(field: FirField, owner: FirClass, irClass: IrClass): IrField? {
// Either take a corresponding constructor property backing field,
// or create a separate delegate field
@@ -866,18 +831,18 @@ class Fir2IrCallableDeclarationsGenerator(val components: Fir2IrComponents) : Fi
fun createIrLocalDelegatedProperty(
property: FirProperty,
irParent: IrDeclarationParent
irParent: IrDeclarationParent,
symbols: LocalDelegatedPropertySymbols
): IrLocalDelegatedProperty = convertCatching(property) {
val type = property.returnTypeRef.toIrType()
val origin = IrDeclarationOrigin.DEFINED
val symbol = IrLocalDelegatedPropertySymbolImpl()
val irProperty = property.convertWithOffsets { startOffset, endOffset ->
irFactory.createLocalDelegatedProperty(
startOffset = startOffset,
endOffset = endOffset,
origin = origin,
name = property.name,
symbol = symbol,
symbol = symbols.propertySymbol,
type = type,
isVar = property.isVar
)
@@ -892,13 +857,13 @@ class Fir2IrCallableDeclarationsGenerator(val components: Fir2IrComponents) : Fi
)
delegate.parent = irParent
getter = createIrPropertyAccessor(
property.getter, property, this, type, irParent, false,
IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR, startOffset, endOffset, dontUseSignature = true
property.getter, property, this, symbols.getterSymbol, type, irParent, false,
IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR, startOffset, endOffset
)
if (property.isVar) {
setter = createIrPropertyAccessor(
property.setter, property, this, type, irParent, true,
IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR, startOffset, endOffset, dontUseSignature = true
property.setter, property, this, symbols.setterSymbol!!, type, irParent, true,
IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR, startOffset, endOffset
)
}
annotationGenerator.generate(this, property)
@@ -1106,4 +1071,3 @@ internal fun addDeclarationToParent(declaration: IrDeclaration, irParent: IrDecl
else -> error("Can't add declaration ${declaration.render()} to parent ${irParent.render()}")
}
}
@@ -6,9 +6,8 @@
package org.jetbrains.kotlin.fir.backend.generators
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.backend.Fir2IrComponents
import org.jetbrains.kotlin.fir.backend.*
import org.jetbrains.kotlin.fir.backend.convertWithOffsets
import org.jetbrains.kotlin.fir.backend.irOrigin
import org.jetbrains.kotlin.fir.backend.isStubPropertyForPureField
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.lazy.*
@@ -16,9 +15,7 @@ import org.jetbrains.kotlin.fir.resolve.providers.firProvider
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorPublicSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldPublicSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrPropertyPublicSymbolImpl
import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.utils.addToStdlib.runIf
@@ -50,39 +47,24 @@ class Fir2IrLazyDeclarationsGenerator(val components: Fir2IrComponents) : Fir2Ir
internal fun createIrLazyProperty(
fir: FirProperty,
signature: IdSignature,
lazyParent: IrDeclarationParent,
symbols: PropertySymbols,
declarationOrigin: IrDeclarationOrigin
): IrProperty {
val symbol = IrPropertyPublicSymbolImpl(signature)
fun create(startOffset: Int, endOffset: Int, isPropertyForField: Boolean): Fir2IrLazyProperty {
val firContainingClass = (lazyParent as? Fir2IrLazyClass)?.fir
val isFakeOverride = !isPropertyForField && fir.isFakeOverride(firContainingClass)
// It is really required to create those properties with DEFINED origin
// Using `declarationOrigin` here (IR_EXTERNAL_JAVA_DECLARATION_STUB in particular) causes some tests to fail, including
// FirPsiBlackBoxCodegenTestGenerated.Reflection.Properties.testJavaStaticField
val originForProperty = if (isPropertyForField) IrDeclarationOrigin.DEFINED else declarationOrigin
return Fir2IrLazyProperty(
components, startOffset, endOffset, originForProperty,
fir, firContainingClass, symbol, isFakeOverride
val isPropertyForField = fir.isStubPropertyForPureField == true
val firContainingClass = (lazyParent as? Fir2IrLazyClass)?.fir
val isFakeOverride = !isPropertyForField && fir.isFakeOverride(firContainingClass)
// It is really required to create those properties with DEFINED origin
// Using `declarationOrigin` here (IR_EXTERNAL_JAVA_DECLARATION_STUB in particular) causes some tests to fail, including
// FirPsiBlackBoxCodegenTestGenerated.Reflection.Properties.testJavaStaticField
val originForProperty = if (isPropertyForField) IrDeclarationOrigin.DEFINED else declarationOrigin
return fir.convertWithOffsets { startOffset, endOffset ->
Fir2IrLazyProperty(
components, startOffset, endOffset, originForProperty, fir, firContainingClass, symbols, isFakeOverride
).apply {
this.parent = lazyParent
}
}
val irProperty = fir.convertWithOffsets { startOffset, endOffset ->
if (fir.isStubPropertyForPureField == true) {
// Very special case when two similar properties can exist so conflicts in SymbolTable are possible.
// See javaCloseFieldAndKotlinProperty.kt in BB tests
symbolTable.declarePropertyWithSignature(signature, symbol)
create(startOffset, endOffset, isPropertyForField = true)
} else {
symbolTable.declareProperty(signature, { symbol }) {
create(startOffset, endOffset, isPropertyForField = false)
}
}
}
return irProperty
}
fun createIrLazyConstructor(
@@ -26,7 +26,6 @@ import org.jetbrains.kotlin.ir.declarations.lazy.lazyVar
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionPublicSymbolImpl
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.NameUtils
@@ -39,9 +38,11 @@ class Fir2IrLazyProperty(
override var origin: IrDeclarationOrigin,
override val fir: FirProperty,
val containingClass: FirRegularClass?,
override val symbol: IrPropertySymbol,
symbols: PropertySymbols,
override var isFakeOverride: Boolean
) : IrProperty(), AbstractFir2IrLazyDeclaration<FirProperty>, Fir2IrComponents by components {
override val symbol: IrPropertySymbol = symbols.propertySymbol
init {
symbol.bind(this)
classifierStorage.preCacheTypeParameters(fir, symbol)
@@ -111,54 +112,51 @@ class Fir2IrLazyProperty(
override var backingField: IrField? by lazyVar(lock) {
when {
fir.hasExplicitBackingField -> {
with(declarationStorage) {
val backingFieldType = with(typeConverter) {
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,
components.visibilityConverter.convertToDescriptorVisibility(visibility),
fir.name,
fir.isVal,
initializer,
backingFieldType
).also { field ->
field.initializer = toIrInitializer(initializer)
}
val backingFieldType = with(typeConverter) {
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 -> {
with(declarationStorage) {
callablesGenerator.createBackingField(
this@Fir2IrLazyProperty,
fir,
IrDeclarationOrigin.PROPERTY_BACKING_FIELD,
components.visibilityConverter.convertToDescriptorVisibility(fir.visibility),
fir.name,
fir.isVal,
fir.initializer,
type
).also { field ->
field.initializer = toIrInitializer(fir.initializer)
}
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 -> {
with(declarationStorage) {
callablesGenerator.createBackingField(
this@Fir2IrLazyProperty,
fir,
IrDeclarationOrigin.PROPERTY_DELEGATE,
components.visibilityConverter.convertToDescriptorVisibility(fir.visibility),
NameUtils.propertyDelegateName(fir.name),
true,
fir.delegate
)
}
callablesGenerator.createBackingField(
this@Fir2IrLazyProperty,
fir,
IrDeclarationOrigin.PROPERTY_DELEGATE,
symbols.backingFieldSymbol!!,
components.visibilityConverter.convertToDescriptorVisibility(fir.visibility),
NameUtils.propertyDelegateName(fir.name),
true,
fir.delegate
)
}
else -> {
null
@@ -172,25 +170,18 @@ class Fir2IrLazyProperty(
}
override var getter: IrSimpleFunction? by lazyVar(lock) {
val signature = signatureComposer.composeAccessorSignature(
fir,
isSetter = false,
containingClass?.symbol?.toLookupTag()
)!!
symbolTable.declareSimpleFunction(signature, symbolFactory = { IrSimpleFunctionPublicSymbolImpl(signature) }) { symbol ->
Fir2IrLazyPropertyAccessor(
components, startOffset, endOffset,
when {
origin == IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB -> origin
fir.delegate != null -> IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR
origin == IrDeclarationOrigin.FAKE_OVERRIDE -> origin
origin == IrDeclarationOrigin.DELEGATED_MEMBER -> origin
fir.getter is FirDefaultPropertyGetter -> IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR
else -> origin
},
fir.getter, isSetter = false, fir, containingClass, symbol, isFakeOverride, this.symbol
)
}.apply {
Fir2IrLazyPropertyAccessor(
components, startOffset, endOffset,
when {
origin == IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB -> origin
fir.delegate != null -> IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR
origin == IrDeclarationOrigin.FAKE_OVERRIDE -> origin
origin == IrDeclarationOrigin.DELEGATED_MEMBER -> origin
fir.getter is FirDefaultPropertyGetter -> IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR
else -> origin
},
fir.getter, isSetter = false, fir, containingClass, symbols.getterSymbol, isFakeOverride, this.symbol
).apply {
parent = this@Fir2IrLazyProperty.parent
correspondingPropertySymbol = this@Fir2IrLazyProperty.symbol
classifiersGenerator.setTypeParameters(this, this@Fir2IrLazyProperty.fir, ConversionTypeOrigin.DEFAULT)
@@ -198,31 +189,22 @@ class Fir2IrLazyProperty(
}
override var setter: IrSimpleFunction? by lazyVar(lock) {
if (!fir.isVar) null
else {
val signature = signatureComposer.composeAccessorSignature(
fir,
isSetter = true,
containingClass?.symbol?.toLookupTag()
)!!
symbolTable.declareSimpleFunction(signature, symbolFactory = { IrSimpleFunctionPublicSymbolImpl(signature) }) { symbol ->
Fir2IrLazyPropertyAccessor(
components, startOffset, endOffset,
when {
origin == IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB -> origin
fir.delegate != null -> IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR
origin == IrDeclarationOrigin.FAKE_OVERRIDE -> origin
origin == IrDeclarationOrigin.DELEGATED_MEMBER -> origin
fir.setter is FirDefaultPropertySetter -> IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR
else -> origin
},
fir.setter, isSetter = true, fir, containingClass, symbol, isFakeOverride, this.symbol
).apply {
parent = this@Fir2IrLazyProperty.parent
correspondingPropertySymbol = this@Fir2IrLazyProperty.symbol
classifiersGenerator.setTypeParameters(this, this@Fir2IrLazyProperty.fir, ConversionTypeOrigin.SETTER)
}
}
if (!fir.isVar) return@lazyVar null
Fir2IrLazyPropertyAccessor(
components, startOffset, endOffset,
when {
origin == IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB -> origin
fir.delegate != null -> IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR
origin == IrDeclarationOrigin.FAKE_OVERRIDE -> origin
origin == IrDeclarationOrigin.DELEGATED_MEMBER -> origin
fir.setter is FirDefaultPropertySetter -> IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR
else -> origin
},
fir.setter, isSetter = true, fir, containingClass, symbols.setterSymbol!!, isFakeOverride, this.symbol
).apply {
parent = this@Fir2IrLazyProperty.parent
correspondingPropertySymbol = this@Fir2IrLazyProperty.symbol
classifiersGenerator.setTypeParameters(this, this@Fir2IrLazyProperty.fir, ConversionTypeOrigin.SETTER)
}
}