[FIR2IR] Don't create IR constructors when their symbol is referenced
KT-62856
This commit is contained in:
committed by
Space Team
parent
55f62834cb
commit
65797e8fba
@@ -238,13 +238,7 @@ class Fir2IrConverter(
|
||||
irClass.declarations.addAll(classifierStorage.getFieldsWithContextReceiversForClass(irClass, klass))
|
||||
|
||||
val irConstructor = klass.primaryConstructorIfAny(session)?.let {
|
||||
if (klass.classKind == ClassKind.ANNOTATION_CLASS) {
|
||||
// TODO: this branch should be removed after fix of KT-62856
|
||||
@OptIn(GetOrCreateSensitiveAPI::class)
|
||||
declarationStorage.getOrCreateIrConstructor(it.fir, irClass, isLocal = klass.isLocal)
|
||||
} else {
|
||||
declarationStorage.createAndCacheIrConstructor(it.fir, { irClass }, isLocal = klass.isLocal)
|
||||
}
|
||||
declarationStorage.createAndCacheIrConstructor(it.fir, { irClass }, isLocal = klass.isLocal)
|
||||
}
|
||||
|
||||
val delegateFieldToPropertyMap = MultiMap<FirProperty, FirField>()
|
||||
@@ -573,13 +567,7 @@ class Fir2IrConverter(
|
||||
}
|
||||
is FirConstructor -> if (!declaration.isPrimary) {
|
||||
// the primary constructor was already created in `processClassMembers` function
|
||||
if (containingClass?.classKind == ClassKind.ANNOTATION_CLASS) {
|
||||
// TODO: this branch should be removed after fix of KT-62856
|
||||
@OptIn(GetOrCreateSensitiveAPI::class)
|
||||
declarationStorage.getOrCreateIrConstructor(declaration, parent as IrClass, isLocal = isInLocalClass)
|
||||
} else {
|
||||
declarationStorage.createAndCacheIrConstructor(declaration, { parent as IrClass }, isLocal = isInLocalClass)
|
||||
}
|
||||
declarationStorage.createAndCacheIrConstructor(declaration, { parent as IrClass }, isLocal = isInLocalClass)
|
||||
}
|
||||
is FirEnumEntry -> {
|
||||
classifierStorage.getOrCreateIrEnumEntry(declaration, parent as IrClass)
|
||||
|
||||
+68
-86
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.fir.descriptors.FirBuiltInsPackageFragment
|
||||
import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor
|
||||
import org.jetbrains.kotlin.fir.java.symbols.FirJavaOverriddenSyntheticPropertySymbol
|
||||
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyClass
|
||||
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyConstructor
|
||||
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyProperty
|
||||
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazySimpleFunction
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.firProvider
|
||||
@@ -29,10 +30,7 @@ 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.*
|
||||
@@ -46,6 +44,7 @@ import org.jetbrains.kotlin.ir.util.createParameterDeclarations
|
||||
import org.jetbrains.kotlin.load.kotlin.FacadeClassSource
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerAbiStability
|
||||
@@ -364,37 +363,8 @@ class Fir2IrDeclarationStorage(
|
||||
|
||||
// ------------------------------------ constructors ------------------------------------
|
||||
|
||||
fun getCachedIrConstructorSymbol(
|
||||
constructor: FirConstructor,
|
||||
signatureCalculator: () -> IdSignature? = { null }
|
||||
): IrConstructorSymbol? {
|
||||
return constructorCache[constructor] ?: signatureCalculator()?.let { signature ->
|
||||
symbolTable.referenceConstructorIfAny(signature)?.also { irConstructorSymbol ->
|
||||
constructorCache[constructor] = irConstructorSymbol
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@GetOrCreateSensitiveAPI
|
||||
fun getOrCreateIrConstructor(
|
||||
constructor: FirConstructor,
|
||||
irParent: IrClass,
|
||||
predefinedOrigin: IrDeclarationOrigin? = null,
|
||||
isLocal: Boolean = false,
|
||||
): IrConstructor {
|
||||
return getOrCreateIrConstructor(constructor, { irParent }, predefinedOrigin, isLocal)
|
||||
}
|
||||
|
||||
@GetOrCreateSensitiveAPI
|
||||
private fun getOrCreateIrConstructor(
|
||||
constructor: FirConstructor,
|
||||
irParent: () -> IrClass,
|
||||
predefinedOrigin: IrDeclarationOrigin? = null,
|
||||
isLocal: Boolean = false,
|
||||
): IrConstructor {
|
||||
@OptIn(UnsafeDuringIrConstructionAPI::class)
|
||||
getCachedIrConstructorSymbol(constructor)?.ownerIfBound()?.let { return it }
|
||||
return createAndCacheIrConstructor(constructor, irParent, predefinedOrigin, isLocal)
|
||||
fun getCachedIrConstructorSymbol(constructor: FirConstructor): IrConstructorSymbol? {
|
||||
return constructorCache[constructor]
|
||||
}
|
||||
|
||||
fun createAndCacheIrConstructor(
|
||||
@@ -403,15 +373,13 @@ class Fir2IrDeclarationStorage(
|
||||
predefinedOrigin: IrDeclarationOrigin? = null,
|
||||
isLocal: Boolean = false,
|
||||
): IrConstructor {
|
||||
// caching of created constructor is not called here, because `callablesGenerator` calls `cacheIrConstructor` by itself
|
||||
val signature = runIf(!isLocal && configuration.linkViaSignatures) {
|
||||
signatureComposer.composeSignature(constructor)
|
||||
}
|
||||
val symbol = getIrConstructorSymbol(constructor.symbol, isLocal)
|
||||
return callablesGenerator.createIrConstructor(
|
||||
constructor,
|
||||
irParent(),
|
||||
createConstructorSymbol(signature),
|
||||
predefinedOrigin
|
||||
symbol,
|
||||
predefinedOrigin,
|
||||
allowLazyDeclarationsCreation = false
|
||||
)
|
||||
}
|
||||
|
||||
@@ -422,17 +390,39 @@ class Fir2IrDeclarationStorage(
|
||||
}
|
||||
}
|
||||
|
||||
@LeakedDeclarationCaches
|
||||
internal fun cacheIrConstructor(constructor: FirConstructor, irConstructor: IrConstructor) {
|
||||
constructorCache[constructor] = irConstructor.symbol
|
||||
private fun cacheIrConstructorSymbol(constructor: FirConstructor, irConstructorSymbol: IrConstructorSymbol) {
|
||||
constructorCache[constructor] = irConstructorSymbol
|
||||
}
|
||||
|
||||
@OptIn(GetOrCreateSensitiveAPI::class)
|
||||
fun getIrConstructorSymbol(firConstructorSymbol: FirConstructorSymbol): IrConstructorSymbol {
|
||||
val fir = firConstructorSymbol.fir
|
||||
return getOrCreateIrConstructor(fir, { findIrParent(fir, fakeOverrideOwnerLookupTag = null) as IrClass }).symbol
|
||||
}
|
||||
fun getIrConstructorSymbol(firConstructorSymbol: FirConstructorSymbol, isLocal: Boolean = false): IrConstructorSymbol {
|
||||
val constructor = firConstructorSymbol.fir
|
||||
getCachedIrConstructorSymbol(constructor)?.let { return it }
|
||||
|
||||
// caching of created constructor is not called here, because `callablesGenerator` calls `cacheIrConstructor` by itself
|
||||
val signature = runIf(!isLocal && configuration.linkViaSignatures) {
|
||||
signatureComposer.composeSignature(constructor)
|
||||
}
|
||||
val symbol = createConstructorSymbol(signature)
|
||||
if (!isLocal) {
|
||||
val irParent = findIrParent(constructor, fakeOverrideOwnerLookupTag = null)
|
||||
val isIntrinsicConstEvaluation =
|
||||
constructor.returnTypeRef.coneType.classId == StandardClassIds.Annotations.IntrinsicConstEvaluation
|
||||
if (irParent.isExternalParent() || isIntrinsicConstEvaluation) {
|
||||
callablesGenerator.createIrConstructor(
|
||||
constructor,
|
||||
irParent as IrClass,
|
||||
symbol,
|
||||
constructor.computeExternalOrigin(),
|
||||
allowLazyDeclarationsCreation = true
|
||||
).also {
|
||||
check(it is Fir2IrLazyConstructor || isIntrinsicConstEvaluation)
|
||||
}
|
||||
}
|
||||
}
|
||||
cacheIrConstructorSymbol(constructor, symbol)
|
||||
|
||||
return symbol
|
||||
}
|
||||
|
||||
// ------------------------------------ properties ------------------------------------
|
||||
|
||||
@@ -987,39 +977,38 @@ class Fir2IrDeclarationStorage(
|
||||
fakeOverrideOwnerLookupTag: ConeClassLikeLookupTag? = null,
|
||||
isLocal: Boolean = false
|
||||
): IrFunctionSymbol {
|
||||
return when (val function = firFunctionSymbol.fir) {
|
||||
is FirConstructor -> {
|
||||
getIrConstructorSymbol(function.symbol)
|
||||
}
|
||||
else -> {
|
||||
getCachedIrFunctionSymbol(function, fakeOverrideOwnerLookupTag)?.let { return it }
|
||||
val signature = runIf(!isLocal && configuration.linkViaSignatures) {
|
||||
signatureComposer.composeSignature(firFunctionSymbol.fir, fakeOverrideOwnerLookupTag)
|
||||
}
|
||||
val symbol = createFunctionSymbol(signature)
|
||||
if (function is FirSimpleFunction && !isLocal) {
|
||||
val irParent = findIrParent(function, fakeOverrideOwnerLookupTag)
|
||||
if (irParent?.isExternalParent() == true) {
|
||||
// Return value is not used here, because creation of IR declaration binds it to the corresponding symbol
|
||||
// And all we want here is to bind symbol for lazy declaration
|
||||
callablesGenerator.createIrFunction(
|
||||
function,
|
||||
irParent,
|
||||
symbol,
|
||||
predefinedOrigin = function.computeExternalOrigin(),
|
||||
isLocal = false,
|
||||
fakeOverrideOwnerLookupTag,
|
||||
allowLazyDeclarationsCreation = true
|
||||
).also {
|
||||
check(it is Fir2IrLazySimpleFunction)
|
||||
}
|
||||
}
|
||||
}
|
||||
val function = firFunctionSymbol.fir
|
||||
|
||||
cacheIrFunctionSymbol(function, symbol, fakeOverrideOwnerLookupTag)
|
||||
return symbol
|
||||
if (function is FirConstructor) {
|
||||
return getIrConstructorSymbol(function.symbol)
|
||||
}
|
||||
|
||||
getCachedIrFunctionSymbol(function, fakeOverrideOwnerLookupTag)?.let { return it }
|
||||
val signature = runIf(!isLocal && configuration.linkViaSignatures) {
|
||||
signatureComposer.composeSignature(firFunctionSymbol.fir, fakeOverrideOwnerLookupTag)
|
||||
}
|
||||
val symbol = createFunctionSymbol(signature)
|
||||
if (function is FirSimpleFunction && !isLocal) {
|
||||
val irParent = findIrParent(function, fakeOverrideOwnerLookupTag)
|
||||
if (irParent?.isExternalParent() == true) {
|
||||
// Return value is not used here, because creation of IR declaration binds it to the corresponding symbol
|
||||
// And all we want here is to bind symbol for lazy declaration
|
||||
callablesGenerator.createIrFunction(
|
||||
function,
|
||||
irParent,
|
||||
symbol,
|
||||
predefinedOrigin = function.computeExternalOrigin(),
|
||||
isLocal = false,
|
||||
fakeOverrideOwnerLookupTag,
|
||||
allowLazyDeclarationsCreation = true
|
||||
).also {
|
||||
check(it is Fir2IrLazySimpleFunction)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cacheIrFunctionSymbol(function, symbol, fakeOverrideOwnerLookupTag)
|
||||
return symbol
|
||||
}
|
||||
|
||||
private inline fun <reified FC : FirCallableDeclaration, reified IS : IrSymbol> getCachedIrCallableSymbol(
|
||||
@@ -1324,13 +1313,6 @@ internal var FirProperty.isStubPropertyForPureField: Boolean? by FirDeclarationD
|
||||
@RequiresOptIn
|
||||
annotation class LeakedDeclarationCaches
|
||||
|
||||
/**
|
||||
* This annotation indicates that an annotated method can create a declaration in ad-hock way, so it should be used with caution
|
||||
* In most cases, it's recommended to use method which return symbol or which forcefully creates a declaration
|
||||
*/
|
||||
@RequiresOptIn
|
||||
annotation class GetOrCreateSensitiveAPI
|
||||
|
||||
/**
|
||||
* This function is introduced as preparation to publishing unbound symbols in fir2ir
|
||||
* There is a probability that it won't be non needed in future, but for now it allows
|
||||
|
||||
@@ -164,7 +164,6 @@ class FirIrProvider(val components: Fir2IrComponents) : IrProvider {
|
||||
val firDeclaration = findDeclarationByHash(firCandidates, signature.id) ?: return null
|
||||
val parent = parentClass ?: declarationStorage.getIrExternalPackageFragment(packageFqName, firDeclaration.moduleData)
|
||||
|
||||
@OptIn(GetOrCreateSensitiveAPI::class)
|
||||
return when (kind) {
|
||||
SymbolKind.CLASS_SYMBOL -> {
|
||||
classifierStorage.getOrCreateIrClass((firDeclaration as FirRegularClass).symbol)
|
||||
@@ -173,8 +172,7 @@ class FirIrProvider(val components: Fir2IrComponents) : IrProvider {
|
||||
firDeclaration as FirEnumEntry, parent as IrClass
|
||||
)
|
||||
SymbolKind.CONSTRUCTOR_SYMBOL -> {
|
||||
val firConstructor = firDeclaration as FirConstructor
|
||||
declarationStorage.getOrCreateIrConstructor(firConstructor, parent as IrClass)
|
||||
shouldNotBeCalled()
|
||||
}
|
||||
SymbolKind.FUNCTION_SYMBOL -> {
|
||||
shouldNotBeCalled()
|
||||
|
||||
+26
-8
@@ -463,19 +463,27 @@ class CallAndReferenceGenerator(
|
||||
explicitReceiver = qualifiedAccess.explicitReceiver
|
||||
)
|
||||
when (symbol) {
|
||||
is IrConstructorSymbol -> IrConstructorCallImpl.fromSymbolOwner(startOffset, endOffset, irType, symbol)
|
||||
is IrConstructorSymbol -> {
|
||||
require(firSymbol is FirConstructorSymbol)
|
||||
val constructor = firSymbol.unwrapCallRepresentative().fir as FirConstructor
|
||||
val totalTypeParametersCount = constructor.typeParameters.size
|
||||
val constructorTypeParametersCount = constructor.typeParameters.count { it is FirTypeParameter }
|
||||
IrConstructorCallImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
irType,
|
||||
symbol,
|
||||
typeArgumentsCount = totalTypeParametersCount,
|
||||
valueArgumentsCount = firSymbol.valueParametersSize(),
|
||||
constructorTypeArgumentsCount = constructorTypeParametersCount,
|
||||
)
|
||||
}
|
||||
is IrSimpleFunctionSymbol -> {
|
||||
require(firSymbol is FirCallableSymbol<*>) { "Illegal symbol: ${firSymbol!!::class}" }
|
||||
val valueParametersNumber = when (firSymbol) {
|
||||
is FirSyntheticPropertySymbol -> 0
|
||||
is FirNamedFunctionSymbol -> firSymbol.valueParameterSymbols.size + firSymbol.resolvedContextReceivers.size
|
||||
is FirFunctionSymbol<*> -> firSymbol.valueParameterSymbols.size
|
||||
else -> error("Illegal symbol: ${firSymbol::class}")
|
||||
}
|
||||
IrCallImpl(
|
||||
startOffset, endOffset, irType, symbol,
|
||||
typeArgumentsCount = firSymbol.typeParameterSymbols.size,
|
||||
valueArgumentsCount = valueParametersNumber,
|
||||
valueArgumentsCount = firSymbol.valueParametersSize(),
|
||||
origin = calleeReference.statementOrigin(),
|
||||
superQualifierSymbol = dispatchReceiver?.superQualifierSymbol()
|
||||
)
|
||||
@@ -553,6 +561,16 @@ class CallAndReferenceGenerator(
|
||||
}
|
||||
}
|
||||
|
||||
private fun FirCallableSymbol<*>.valueParametersSize(): Int {
|
||||
return when (this) {
|
||||
is FirSyntheticPropertySymbol -> 0
|
||||
is FirNamedFunctionSymbol -> fir.valueParameters.size + fir.contextReceivers.size
|
||||
is FirConstructorSymbol -> fir.valueParameters.size + fir.contextReceivers.size
|
||||
is FirFunctionSymbol<*> -> fir.valueParameters.size
|
||||
else -> error("Illegal symbol: ${this::class}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun convertToIrSetCallForDynamic(
|
||||
variableAssignment: FirVariableAssignment,
|
||||
explicitReceiverExpression: IrExpression?,
|
||||
|
||||
+6
-13
@@ -45,10 +45,7 @@ import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.NameUtils
|
||||
import org.jetbrains.kotlin.name.SpecialNames
|
||||
import org.jetbrains.kotlin.name.*
|
||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||
import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
@@ -176,15 +173,15 @@ class Fir2IrCallableDeclarationsGenerator(val components: Fir2IrComponents) : Fi
|
||||
irParent: IrClass,
|
||||
symbol: IrConstructorSymbol,
|
||||
predefinedOrigin: IrDeclarationOrigin? = null,
|
||||
allowLazyDeclarationsCreation: Boolean
|
||||
): IrConstructor = convertCatching(constructor) {
|
||||
val origin = constructor.computeIrOrigin(predefinedOrigin, irParent.origin)
|
||||
val isPrimary = constructor.isPrimary
|
||||
if (irParent is Fir2IrLazyClass) {
|
||||
val lazyConstructor = lazyDeclarationsGenerator.createIrLazyConstructor(constructor, symbol, origin, irParent) as Fir2IrLazyConstructor
|
||||
// Add to cache before generating parameters to prevent an infinite loop when an annotation value parameter is annotated
|
||||
// with the annotation itself.
|
||||
@OptIn(LeakedDeclarationCaches::class)
|
||||
declarationStorage.cacheIrConstructor(constructor, lazyConstructor)
|
||||
if (!allowLazyDeclarationsCreation) {
|
||||
error("Lazy constructors should be processed in Fir2IrDeclarationStorage")
|
||||
}
|
||||
val lazyConstructor = lazyDeclarationsGenerator.createIrLazyConstructor(constructor, symbol, origin, irParent)
|
||||
lazyConstructor.prepareTypeParameters()
|
||||
return lazyConstructor
|
||||
}
|
||||
@@ -206,10 +203,6 @@ class Fir2IrCallableDeclarationsGenerator(val components: Fir2IrComponents) : Fi
|
||||
).apply {
|
||||
metadata = FirMetadataSource.Function(constructor)
|
||||
annotationGenerator.generate(this, constructor)
|
||||
// Add to cache before generating parameters to prevent an infinite loop when an annotation value parameter is annotated
|
||||
// with the annotation itself.
|
||||
@OptIn(LeakedDeclarationCaches::class)
|
||||
declarationStorage.cacheIrConstructor(constructor, this)
|
||||
declarationStorage.withScope(symbol) {
|
||||
setParent(irParent)
|
||||
addDeclarationToParent(this, irParent)
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ class Fir2IrLazyDeclarationsGenerator(val components: Fir2IrComponents) : Fir2Ir
|
||||
symbol: IrConstructorSymbol,
|
||||
declarationOrigin: IrDeclarationOrigin,
|
||||
lazyParent: IrDeclarationParent,
|
||||
): IrConstructor = fir.convertWithOffsets { startOffset, endOffset ->
|
||||
): Fir2IrLazyConstructor = fir.convertWithOffsets { startOffset, endOffset ->
|
||||
Fir2IrLazyConstructor(components, startOffset, endOffset, declarationOrigin, fir, symbol, lazyParent)
|
||||
}
|
||||
|
||||
|
||||
@@ -164,8 +164,9 @@ class Fir2IrLazyClass(
|
||||
scope.processDeclaredConstructors {
|
||||
val constructor = it.fir
|
||||
if (shouldBuildStub(constructor)) {
|
||||
@OptIn(GetOrCreateSensitiveAPI::class)
|
||||
result += declarationStorage.getOrCreateIrConstructor(constructor, this, origin)
|
||||
// Lazy declarations are created together with their symbol, so it's safe to take the owner here
|
||||
@OptIn(UnsafeDuringIrConstructionAPI::class)
|
||||
result += declarationStorage.getIrConstructorSymbol(constructor.symbol).owner
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user