[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.*
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.isStatic import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.declarations.utils.nameOrSpecialName
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.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.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.ConeKotlinType import org.jetbrains.kotlin.fir.types.*
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.*
import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl
import org.jetbrains.kotlin.ir.expressions.IrSyntheticBodyKind import org.jetbrains.kotlin.ir.expressions.IrSyntheticBodyKind
import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.*
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.util.IdSignature import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.ir.util.classId import org.jetbrains.kotlin.ir.util.classId
import org.jetbrains.kotlin.ir.util.createParameterDeclarations import org.jetbrains.kotlin.ir.util.createParameterDeclarations
@@ -543,11 +536,54 @@ class Fir2IrDeclarationStorage(
): IrProperty { ): IrProperty {
@Suppress("NAME_SHADOWING") @Suppress("NAME_SHADOWING")
val property = prepareProperty(property) 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) cacheIrProperty(property, irProperty, fakeOverrideOwnerLookupTag)
return irProperty 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( private fun cacheIrProperty(
property: FirProperty, property: FirProperty,
irProperty: IrProperty, irProperty: IrProperty,
@@ -773,6 +809,10 @@ class Fir2IrDeclarationStorage(
return irField return irField
} }
private fun createFieldSymbol(): IrFieldSymbol {
return IrFieldSymbolImpl()
}
// This function returns null if this field/ownerClassId combination does not describe static fake override // This function returns null if this field/ownerClassId combination does not describe static fake override
private fun getFieldStaticFakeOverrideKey(field: FirField, ownerLookupTag: ConeClassLikeLookupTag?): FieldStaticOverrideKey? { private fun getFieldStaticFakeOverrideKey(field: FirField, ownerLookupTag: ConeClassLikeLookupTag?): FieldStaticOverrideKey? {
if (ownerLookupTag == null || !field.isStatic || if (ownerLookupTag == null || !field.isStatic ||
@@ -825,7 +865,8 @@ class Fir2IrDeclarationStorage(
property: FirProperty, property: FirProperty,
irParent: IrDeclarationParent irParent: IrDeclarationParent
): IrLocalDelegatedProperty { ): IrLocalDelegatedProperty {
val irProperty = callablesGenerator.createIrLocalDelegatedProperty(property, irParent) val symbols = createLocalDelegatedPropertySymbols(property)
val irProperty = callablesGenerator.createIrLocalDelegatedProperty(property, irParent, symbols)
val symbol = irProperty.symbol val symbol = irProperty.symbol
delegateVariableForPropertyCache[symbol] = irProperty.delegate.symbol delegateVariableForPropertyCache[symbol] = irProperty.delegate.symbol
getterForPropertyCache[symbol] = irProperty.getter.symbol getterForPropertyCache[symbol] = irProperty.getter.symbol
@@ -834,6 +875,15 @@ class Fir2IrDeclarationStorage(
return irProperty 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 ------------------------------------ // ------------------------------------ variables ------------------------------------
fun createAndCacheIrVariable( fun createAndCacheIrVariable(
@@ -1244,3 +1294,16 @@ annotation class GetOrCreateSensitiveAPI
internal fun <D : IrDeclaration> IrBindableSymbol<*, D>.ownerIfBound(): D? { internal fun <D : IrDeclaration> IrBindableSymbol<*, D>.ownerIfBound(): D? {
return runIf(isBound) { owner } 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 ------------------------------------ // ------------------------------------ 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( fun createIrFunction(
function: FirFunction, function: FirFunction,
irParent: IrDeclarationParent?, irParent: IrDeclarationParent?,
@@ -228,19 +217,10 @@ class Fir2IrCallableDeclarationsGenerator(val components: Fir2IrComponents) : Fi
// ------------------------------------ properties ------------------------------------ // ------------------------------------ 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( fun createIrProperty(
property: FirProperty, property: FirProperty,
irParent: IrDeclarationParent?, irParent: IrDeclarationParent?,
symbols: PropertySymbols,
predefinedOrigin: IrDeclarationOrigin? = null, predefinedOrigin: IrDeclarationOrigin? = null,
isLocal: Boolean = false, isLocal: Boolean = false,
fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag? = null, fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag? = null,
@@ -270,118 +250,115 @@ class Fir2IrCallableDeclarationsGenerator(val components: Fir2IrComponents) : Fi
} }
if (parentIsExternal && signature != null) { if (parentIsExternal && signature != null) {
// 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, signature, irParent!!, origin) return lazyDeclarationsGenerator.createIrLazyProperty(property, irParent!!, symbols, origin)
} }
return property.convertWithOffsets { startOffset, endOffset -> return property.convertWithOffsets { startOffset, endOffset ->
val result = declareIrProperty(signature) { symbol -> classifierStorage.preCacheTypeParameters(property, symbols.propertySymbol)
classifierStorage.preCacheTypeParameters(property, symbol) irFactory.createProperty(
irFactory.createProperty( startOffset = startOffset,
startOffset = startOffset, endOffset = endOffset,
endOffset = endOffset, origin = origin,
origin = origin, name = property.name,
name = property.name, visibility = components.visibilityConverter.convertToDescriptorVisibility(property.visibility),
visibility = components.visibilityConverter.convertToDescriptorVisibility(property.visibility), modality = property.modality!!,
modality = property.modality!!, symbol = symbols.propertySymbol,
symbol = symbol, isVar = property.isVar,
isVar = property.isVar, isConst = property.isConst,
isConst = property.isConst, isLateinit = property.isLateInit,
isLateinit = property.isLateInit, isDelegated = property.delegate != null,
isDelegated = property.delegate != null, isExternal = property.isExternal,
isExternal = property.isExternal, containerSource = property.containerSource,
containerSource = property.containerSource, isExpect = property.isExpect,
isExpect = property.isExpect, ).apply {
).apply { metadata = FirMetadataSource.Property(property)
metadata = FirMetadataSource.Property(property) convertAnnotationsForNonDeclaredMembers(property, origin)
convertAnnotationsForNonDeclaredMembers(property, origin) declarationStorage.withScope(symbol) {
declarationStorage.withScope(symbol) { // IrProperty is never created for local variables
// IrProperty is never created for local variables setParent(irParent)
setParent(irParent) addDeclarationToParent(this, irParent)
addDeclarationToParent(this, irParent) val type = property.returnTypeRef.toIrType()
val type = property.returnTypeRef.toIrType() val delegate = property.delegate
val delegate = property.delegate val getter = property.getter
val getter = property.getter val setter = property.setter
val setter = property.setter if (delegate != null || property.hasBackingField) {
if (delegate != null || property.hasBackingField) { val backingField = if (delegate != null) {
val backingField = if (delegate != null) { ((delegate as? FirQualifiedAccessExpression)?.calleeReference?.toResolvedBaseSymbol()?.fir as? FirTypeParameterRefsOwner)?.let {
((delegate as? FirQualifiedAccessExpression)?.calleeReference?.toResolvedBaseSymbol()?.fir as? FirTypeParameterRefsOwner)?.let { classifierStorage.preCacheTypeParameters(it, symbol)
classifierStorage.preCacheTypeParameters(it, symbol) }
} createBackingField(
createBackingField( this,
this, property,
property, IrDeclarationOrigin.PROPERTY_DELEGATE,
IrDeclarationOrigin.PROPERTY_DELEGATE, symbols.backingFieldSymbol!!,
components.visibilityConverter.convertToDescriptorVisibility(property.fieldVisibility), components.visibilityConverter.convertToDescriptorVisibility(property.fieldVisibility),
NameUtils.propertyDelegateName(property.name), NameUtils.propertyDelegateName(property.name),
true, true,
delegate delegate
) )
} else { } else {
val initializer = getEffectivePropertyInitializer(property, resolveIfNeeded = true) val initializer = getEffectivePropertyInitializer(property, resolveIfNeeded = true)
// There are cases when we get here for properties // There are cases when we get here for properties
// that have no backing field. For example, in the // that have no backing field. For example, in the
// funExpression.kt test there's an attempt // funExpression.kt test there's an attempt
// to access the `javaClass` property of the `foo0`'s // to access the `javaClass` property of the `foo0`'s
// `block` argument // `block` argument
val typeToUse = property.backingField?.returnTypeRef?.toIrType() ?: type val typeToUse = property.backingField?.returnTypeRef?.toIrType() ?: type
createBackingField( createBackingField(
this, this,
property, property,
IrDeclarationOrigin.PROPERTY_BACKING_FIELD, IrDeclarationOrigin.PROPERTY_BACKING_FIELD,
components.visibilityConverter.convertToDescriptorVisibility(property.fieldVisibility), symbols.backingFieldSymbol!!,
property.name, components.visibilityConverter.convertToDescriptorVisibility(property.fieldVisibility),
property.isVal, property.name,
initializer, property.isVal,
typeToUse initializer,
).also { field -> typeToUse
if (initializer is FirConstExpression<*>) { ).also { field ->
val constType = initializer.resolvedType.toIrType() if (initializer is FirConstExpression<*>) {
field.initializer = factory.createExpressionBody(initializer.toIrConst(constType)) val constType = initializer.resolvedType.toIrType()
} field.initializer = factory.createExpressionBody(initializer.toIrConst(constType))
} }
} }
this.backingField = backingField
} }
if (irParent != null) { this.backingField = backingField
backingField?.parent = irParent }
} if (irParent != null) {
this.getter = getter.convertWithOffsets(startOffset, endOffset) { startOffset, endOffset -> 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( createIrPropertyAccessor(
getter, property, this, type, irParent, false, setter, property, this, symbols.setterSymbol!!, type, irParent, true,
when { when {
origin == IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB -> origin
origin == IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER -> origin
delegate != null -> IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR delegate != null -> IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR
origin == IrDeclarationOrigin.FAKE_OVERRIDE -> origin origin == IrDeclarationOrigin.FAKE_OVERRIDE -> origin
origin == IrDeclarationOrigin.DELEGATED_MEMBER -> origin origin == IrDeclarationOrigin.DELEGATED_MEMBER -> origin
getter == null || getter is FirDefaultPropertyGetter -> IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR setter is FirDefaultPropertySetter -> IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR
else -> origin else -> origin
}, },
startOffset, endOffset, startOffset, endOffset,
dontUseSignature = signature == null, fakeOverrideOwnerLookupTag, property.unwrapFakeOverrides().setter,
property.unwrapFakeOverrides().getter,
) )
} }
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?, propertyAccessor: FirPropertyAccessor?,
property: FirProperty, property: FirProperty,
correspondingProperty: IrDeclarationWithName, correspondingProperty: IrDeclarationWithName,
symbol: IrSimpleFunctionSymbol,
propertyType: IrType, propertyType: IrType,
irParent: IrDeclarationParent?, irParent: IrDeclarationParent?,
isSetter: Boolean, isSetter: Boolean,
origin: IrDeclarationOrigin, origin: IrDeclarationOrigin,
startOffset: Int, startOffset: Int,
endOffset: Int, endOffset: Int,
dontUseSignature: Boolean = false,
fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag? = null,
propertyAccessorForAnnotations: FirPropertyAccessor? = propertyAccessor, propertyAccessorForAnnotations: FirPropertyAccessor? = propertyAccessor,
): IrSimpleFunction = convertCatching(propertyAccessor ?: property) { ): IrSimpleFunction = convertCatching(propertyAccessor ?: property) {
val prefix = if (isSetter) "set" else "get" val prefix = if (isSetter) "set" else "get"
val signature =
runUnless(dontUseSignature) {
signatureComposer.composeAccessorSignature(property, isSetter, fakeOverrideOwnerLookupTag)
}
val containerSource = (correspondingProperty as? IrProperty)?.containerSource val containerSource = (correspondingProperty as? IrProperty)?.containerSource
return declareIrSimpleFunction(signature) { symbol -> val accessorReturnType = if (isSetter) irBuiltIns.unitType else propertyType
val accessorReturnType = if (isSetter) irBuiltIns.unitType else propertyType val visibility = propertyAccessor?.visibility?.let {
val visibility = propertyAccessor?.visibility?.let { components.visibilityConverter.convertToDescriptorVisibility(it)
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) { if (propertyAccessorForAnnotations != null) {
convertAnnotationsForNonDeclaredMembers(propertyAccessorForAnnotations, origin) 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( // property accessors does not belong to declarations of class/file, but are referenced via property,
this, property, if (isSetter) ConversionTypeOrigin.SETTER else ConversionTypeOrigin.DEFAULT // 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, irProperty: IrProperty,
firProperty: FirProperty, firProperty: FirProperty,
origin: IrDeclarationOrigin, origin: IrDeclarationOrigin,
symbol: IrFieldSymbol,
visibility: DescriptorVisibility, visibility: DescriptorVisibility,
name: Name, name: Name,
isFinal: Boolean, isFinal: Boolean,
@@ -532,25 +503,23 @@ class Fir2IrCallableDeclarationsGenerator(val components: Fir2IrComponents) : Fi
type: IrType? = null type: IrType? = null
): IrField = convertCatching(firProperty) { ): IrField = convertCatching(firProperty) {
val inferredType = type ?: firInitializerExpression!!.resolvedType.toIrType() val inferredType = type ?: firInitializerExpression!!.resolvedType.toIrType()
return declareIrField { symbol -> return (firProperty.delegate ?: firProperty.backingField ?: firProperty).convertWithOffsets { startOffset: Int, endOffset: Int ->
(firProperty.delegate ?: firProperty.backingField ?: firProperty).convertWithOffsets { startOffset: Int, endOffset: Int -> irFactory.createField(
irFactory.createField( startOffset = startOffset,
startOffset = startOffset, endOffset = endOffset,
endOffset = endOffset, origin = origin,
origin = origin, name = name,
name = name, visibility = visibility,
visibility = visibility, symbol = symbol,
symbol = symbol, type = inferredType,
type = inferredType, isFinal = isFinal,
isFinal = isFinal, isStatic = firProperty.isStatic || !(irProperty.parent is IrClass || irProperty.parent is IrScript),
isStatic = firProperty.isStatic || !(irProperty.parent is IrClass || irProperty.parent is IrScript), isExternal = firProperty.isExternal,
isExternal = firProperty.isExternal, ).also {
).also { it.correspondingPropertySymbol = irProperty.symbol
it.correspondingPropertySymbol = irProperty.symbol }.apply {
}.apply { metadata = FirMetadataSource.Property(firProperty)
metadata = FirMetadataSource.Property(firProperty) convertAnnotationsForNonDeclaredMembers(firProperty, origin)
convertAnnotationsForNonDeclaredMembers(firProperty, origin)
}
} }
} }
} }
@@ -565,10 +534,6 @@ class Fir2IrCallableDeclarationsGenerator(val components: Fir2IrComponents) : Fi
else -> Visibilities.Private else -> Visibilities.Private
} }
private fun declareIrField(factory: (IrFieldSymbol) -> IrField): IrField {
return factory(IrFieldSymbolImpl())
}
fun createIrFieldAndDelegatedMembers(field: FirField, owner: FirClass, irClass: IrClass): IrField? { fun createIrFieldAndDelegatedMembers(field: FirField, owner: FirClass, irClass: IrClass): IrField? {
// Either take a corresponding constructor property backing field, // Either take a corresponding constructor property backing field,
// or create a separate delegate field // or create a separate delegate field
@@ -866,18 +831,18 @@ class Fir2IrCallableDeclarationsGenerator(val components: Fir2IrComponents) : Fi
fun createIrLocalDelegatedProperty( fun createIrLocalDelegatedProperty(
property: FirProperty, property: FirProperty,
irParent: IrDeclarationParent irParent: IrDeclarationParent,
symbols: LocalDelegatedPropertySymbols
): IrLocalDelegatedProperty = convertCatching(property) { ): IrLocalDelegatedProperty = convertCatching(property) {
val type = property.returnTypeRef.toIrType() val type = property.returnTypeRef.toIrType()
val origin = IrDeclarationOrigin.DEFINED val origin = IrDeclarationOrigin.DEFINED
val symbol = IrLocalDelegatedPropertySymbolImpl()
val irProperty = property.convertWithOffsets { startOffset, endOffset -> val irProperty = property.convertWithOffsets { startOffset, endOffset ->
irFactory.createLocalDelegatedProperty( irFactory.createLocalDelegatedProperty(
startOffset = startOffset, startOffset = startOffset,
endOffset = endOffset, endOffset = endOffset,
origin = origin, origin = origin,
name = property.name, name = property.name,
symbol = symbol, symbol = symbols.propertySymbol,
type = type, type = type,
isVar = property.isVar isVar = property.isVar
) )
@@ -892,13 +857,13 @@ class Fir2IrCallableDeclarationsGenerator(val components: Fir2IrComponents) : Fi
) )
delegate.parent = irParent delegate.parent = irParent
getter = createIrPropertyAccessor( getter = createIrPropertyAccessor(
property.getter, property, this, type, irParent, false, property.getter, property, this, symbols.getterSymbol, type, irParent, false,
IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR, startOffset, endOffset, dontUseSignature = true IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR, startOffset, endOffset
) )
if (property.isVar) { if (property.isVar) {
setter = createIrPropertyAccessor( setter = createIrPropertyAccessor(
property.setter, property, this, type, irParent, true, property.setter, property, this, symbols.setterSymbol!!, type, irParent, true,
IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR, startOffset, endOffset, dontUseSignature = true IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR, startOffset, endOffset
) )
} }
annotationGenerator.generate(this, property) 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()}") else -> error("Can't add declaration ${declaration.render()} to parent ${irParent.render()}")
} }
} }
@@ -6,9 +6,8 @@
package org.jetbrains.kotlin.fir.backend.generators package org.jetbrains.kotlin.fir.backend.generators
import org.jetbrains.kotlin.fir.* 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.convertWithOffsets
import org.jetbrains.kotlin.fir.backend.irOrigin
import org.jetbrains.kotlin.fir.backend.isStubPropertyForPureField import org.jetbrains.kotlin.fir.backend.isStubPropertyForPureField
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.lazy.* 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.declarations.*
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol 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.IrFieldPublicSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrPropertyPublicSymbolImpl
import org.jetbrains.kotlin.ir.util.IdSignature import org.jetbrains.kotlin.ir.util.IdSignature
import org.jetbrains.kotlin.utils.addToStdlib.runIf import org.jetbrains.kotlin.utils.addToStdlib.runIf
@@ -50,39 +47,24 @@ class Fir2IrLazyDeclarationsGenerator(val components: Fir2IrComponents) : Fir2Ir
internal fun createIrLazyProperty( internal fun createIrLazyProperty(
fir: FirProperty, fir: FirProperty,
signature: IdSignature,
lazyParent: IrDeclarationParent, lazyParent: IrDeclarationParent,
symbols: PropertySymbols,
declarationOrigin: IrDeclarationOrigin declarationOrigin: IrDeclarationOrigin
): IrProperty { ): IrProperty {
val symbol = IrPropertyPublicSymbolImpl(signature) val isPropertyForField = fir.isStubPropertyForPureField == true
fun create(startOffset: Int, endOffset: Int, isPropertyForField: Boolean): Fir2IrLazyProperty { val firContainingClass = (lazyParent as? Fir2IrLazyClass)?.fir
val firContainingClass = (lazyParent as? Fir2IrLazyClass)?.fir val isFakeOverride = !isPropertyForField && fir.isFakeOverride(firContainingClass)
val isFakeOverride = !isPropertyForField && fir.isFakeOverride(firContainingClass) // It is really required to create those properties with DEFINED origin
// 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
// Using `declarationOrigin` here (IR_EXTERNAL_JAVA_DECLARATION_STUB in particular) causes some tests to fail, including // FirPsiBlackBoxCodegenTestGenerated.Reflection.Properties.testJavaStaticField
// FirPsiBlackBoxCodegenTestGenerated.Reflection.Properties.testJavaStaticField val originForProperty = if (isPropertyForField) IrDeclarationOrigin.DEFINED else declarationOrigin
val originForProperty = if (isPropertyForField) IrDeclarationOrigin.DEFINED else declarationOrigin return fir.convertWithOffsets { startOffset, endOffset ->
return Fir2IrLazyProperty( Fir2IrLazyProperty(
components, startOffset, endOffset, originForProperty, components, startOffset, endOffset, originForProperty, fir, firContainingClass, symbols, isFakeOverride
fir, firContainingClass, symbol, isFakeOverride
).apply { ).apply {
this.parent = lazyParent 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( 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.IrConstructorCall
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol 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.ir.types.IrType
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.NameUtils import org.jetbrains.kotlin.name.NameUtils
@@ -39,9 +38,11 @@ class Fir2IrLazyProperty(
override var origin: IrDeclarationOrigin, override var origin: IrDeclarationOrigin,
override val fir: FirProperty, override val fir: FirProperty,
val containingClass: FirRegularClass?, val containingClass: FirRegularClass?,
override val symbol: IrPropertySymbol, symbols: PropertySymbols,
override var isFakeOverride: Boolean override var isFakeOverride: Boolean
) : IrProperty(), AbstractFir2IrLazyDeclaration<FirProperty>, Fir2IrComponents by components { ) : IrProperty(), AbstractFir2IrLazyDeclaration<FirProperty>, Fir2IrComponents by components {
override val symbol: IrPropertySymbol = symbols.propertySymbol
init { init {
symbol.bind(this) symbol.bind(this)
classifierStorage.preCacheTypeParameters(fir, symbol) classifierStorage.preCacheTypeParameters(fir, symbol)
@@ -111,54 +112,51 @@ class Fir2IrLazyProperty(
override var backingField: IrField? by lazyVar(lock) { override var backingField: IrField? by lazyVar(lock) {
when { when {
fir.hasExplicitBackingField -> { fir.hasExplicitBackingField -> {
with(declarationStorage) { val backingFieldType = with(typeConverter) {
val backingFieldType = with(typeConverter) { fir.backingField?.returnTypeRef?.toIrType()
fir.backingField?.returnTypeRef?.toIrType() }
} val initializer = fir.backingField?.initializer ?: fir.initializer
val initializer = fir.backingField?.initializer ?: fir.initializer val visibility = fir.backingField?.visibility ?: fir.visibility
val visibility = fir.backingField?.visibility ?: fir.visibility callablesGenerator.createBackingField(
callablesGenerator.createBackingField( this@Fir2IrLazyProperty,
this@Fir2IrLazyProperty, fir,
fir, IrDeclarationOrigin.PROPERTY_BACKING_FIELD,
IrDeclarationOrigin.PROPERTY_BACKING_FIELD, symbols.backingFieldSymbol!!,
components.visibilityConverter.convertToDescriptorVisibility(visibility), components.visibilityConverter.convertToDescriptorVisibility(visibility),
fir.name, fir.name,
fir.isVal, fir.isVal,
initializer, initializer,
backingFieldType backingFieldType
).also { field -> ).also { field ->
field.initializer = toIrInitializer(initializer) field.initializer = toIrInitializer(initializer)
}
} }
} }
extensions.hasBackingField(fir, session) && origin != IrDeclarationOrigin.FAKE_OVERRIDE -> { extensions.hasBackingField(fir, session) && origin != IrDeclarationOrigin.FAKE_OVERRIDE -> {
with(declarationStorage) { callablesGenerator.createBackingField(
callablesGenerator.createBackingField( this@Fir2IrLazyProperty,
this@Fir2IrLazyProperty, fir,
fir, IrDeclarationOrigin.PROPERTY_BACKING_FIELD,
IrDeclarationOrigin.PROPERTY_BACKING_FIELD, symbols.backingFieldSymbol!!,
components.visibilityConverter.convertToDescriptorVisibility(fir.visibility), components.visibilityConverter.convertToDescriptorVisibility(fir.visibility),
fir.name, fir.name,
fir.isVal, fir.isVal,
fir.initializer, fir.initializer,
type type
).also { field -> ).also { field ->
field.initializer = toIrInitializer(fir.initializer) field.initializer = toIrInitializer(fir.initializer)
}
} }
} }
fir.delegate != null -> { fir.delegate != null -> {
with(declarationStorage) { callablesGenerator.createBackingField(
callablesGenerator.createBackingField( this@Fir2IrLazyProperty,
this@Fir2IrLazyProperty, fir,
fir, IrDeclarationOrigin.PROPERTY_DELEGATE,
IrDeclarationOrigin.PROPERTY_DELEGATE, symbols.backingFieldSymbol!!,
components.visibilityConverter.convertToDescriptorVisibility(fir.visibility), components.visibilityConverter.convertToDescriptorVisibility(fir.visibility),
NameUtils.propertyDelegateName(fir.name), NameUtils.propertyDelegateName(fir.name),
true, true,
fir.delegate fir.delegate
) )
}
} }
else -> { else -> {
null null
@@ -172,25 +170,18 @@ class Fir2IrLazyProperty(
} }
override var getter: IrSimpleFunction? by lazyVar(lock) { override var getter: IrSimpleFunction? by lazyVar(lock) {
val signature = signatureComposer.composeAccessorSignature( Fir2IrLazyPropertyAccessor(
fir, components, startOffset, endOffset,
isSetter = false, when {
containingClass?.symbol?.toLookupTag() origin == IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB -> origin
)!! fir.delegate != null -> IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR
symbolTable.declareSimpleFunction(signature, symbolFactory = { IrSimpleFunctionPublicSymbolImpl(signature) }) { symbol -> origin == IrDeclarationOrigin.FAKE_OVERRIDE -> origin
Fir2IrLazyPropertyAccessor( origin == IrDeclarationOrigin.DELEGATED_MEMBER -> origin
components, startOffset, endOffset, fir.getter is FirDefaultPropertyGetter -> IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR
when { else -> origin
origin == IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB -> origin },
fir.delegate != null -> IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR fir.getter, isSetter = false, fir, containingClass, symbols.getterSymbol, isFakeOverride, this.symbol
origin == IrDeclarationOrigin.FAKE_OVERRIDE -> origin ).apply {
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 {
parent = this@Fir2IrLazyProperty.parent parent = this@Fir2IrLazyProperty.parent
correspondingPropertySymbol = this@Fir2IrLazyProperty.symbol correspondingPropertySymbol = this@Fir2IrLazyProperty.symbol
classifiersGenerator.setTypeParameters(this, this@Fir2IrLazyProperty.fir, ConversionTypeOrigin.DEFAULT) classifiersGenerator.setTypeParameters(this, this@Fir2IrLazyProperty.fir, ConversionTypeOrigin.DEFAULT)
@@ -198,31 +189,22 @@ class Fir2IrLazyProperty(
} }
override var setter: IrSimpleFunction? by lazyVar(lock) { override var setter: IrSimpleFunction? by lazyVar(lock) {
if (!fir.isVar) null if (!fir.isVar) return@lazyVar null
else { Fir2IrLazyPropertyAccessor(
val signature = signatureComposer.composeAccessorSignature( components, startOffset, endOffset,
fir, when {
isSetter = true, origin == IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB -> origin
containingClass?.symbol?.toLookupTag() fir.delegate != null -> IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR
)!! origin == IrDeclarationOrigin.FAKE_OVERRIDE -> origin
symbolTable.declareSimpleFunction(signature, symbolFactory = { IrSimpleFunctionPublicSymbolImpl(signature) }) { symbol -> origin == IrDeclarationOrigin.DELEGATED_MEMBER -> origin
Fir2IrLazyPropertyAccessor( fir.setter is FirDefaultPropertySetter -> IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR
components, startOffset, endOffset, else -> origin
when { },
origin == IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB -> origin fir.setter, isSetter = true, fir, containingClass, symbols.setterSymbol!!, isFakeOverride, this.symbol
fir.delegate != null -> IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR ).apply {
origin == IrDeclarationOrigin.FAKE_OVERRIDE -> origin parent = this@Fir2IrLazyProperty.parent
origin == IrDeclarationOrigin.DELEGATED_MEMBER -> origin correspondingPropertySymbol = this@Fir2IrLazyProperty.symbol
fir.setter is FirDefaultPropertySetter -> IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR classifiersGenerator.setTypeParameters(this, this@Fir2IrLazyProperty.fir, ConversionTypeOrigin.SETTER)
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)
}
}
} }
} }