diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt index 0f97a3fbe3c..2e62eeda0a7 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt @@ -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() @@ -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) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt index 517fb02de4e..7bf809555a9 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt @@ -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 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 diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/FirIrProvider.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/FirIrProvider.kt index 6ae09523e92..20adba597eb 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/FirIrProvider.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/FirIrProvider.kt @@ -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() diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt index bae5e6a8515..08d048e2281 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt @@ -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?, diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrCallableDeclarationsGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrCallableDeclarationsGenerator.kt index 98b35fcc2ee..4f035db56fd 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrCallableDeclarationsGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrCallableDeclarationsGenerator.kt @@ -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) diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrLazyDeclarationsGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrLazyDeclarationsGenerator.kt index fe8fb0fea01..6e38348fb4a 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrLazyDeclarationsGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/Fir2IrLazyDeclarationsGenerator.kt @@ -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) } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyClass.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyClass.kt index b1843e3a9d0..0834646ace7 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyClass.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazyClass.kt @@ -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 } }