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 33a241ea5af..b8e8ea41c2a 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 @@ -513,7 +513,7 @@ class Fir2IrDeclarationStorage( predefinedOrigin: IrDeclarationOrigin? = null, isLocal: Boolean = false, ): IrConstructor { - val symbol = getIrConstructorSymbol(constructor.symbol, isLocal) + val symbol = getIrConstructorSymbol(constructor.symbol, potentiallyExternal = !isLocal) return callablesGenerator.createIrConstructor( constructor, irParent(), @@ -527,13 +527,13 @@ class Fir2IrDeclarationStorage( constructorCache[constructor] = irConstructorSymbol } - fun getIrConstructorSymbol(firConstructorSymbol: FirConstructorSymbol, isLocal: Boolean = false): IrConstructorSymbol { + fun getIrConstructorSymbol(firConstructorSymbol: FirConstructorSymbol, potentiallyExternal: Boolean = true): 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 symbol = IrConstructorSymbolImpl() - if (!isLocal) { + if (potentiallyExternal) { val irParent = findIrParent(constructor, fakeOverrideOwnerLookupTag = null) val isIntrinsicConstEvaluation = constructor.returnTypeRef.coneType.classId == StandardClassIds.Annotations.IntrinsicConstEvaluation diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrTypeConverter.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrTypeConverter.kt index 85649e74962..8fb6a712274 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrTypeConverter.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrTypeConverter.kt @@ -51,7 +51,7 @@ class Fir2IrTypeConverter( StandardClassIds.Double to irBuiltIns.doubleClass, StandardClassIds.Char to irBuiltIns.charClass, StandardClassIds.Array to irBuiltIns.arrayClass, - StandardClassIds.Annotations.IntrinsicConstEvaluation to irBuiltIns.intrinsicConst + StandardClassIds.Annotations.IntrinsicConstEvaluation to irBuiltIns.intrinsicConstSymbol ) } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/IrBuiltInsOverFir.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/IrBuiltInsOverFir.kt index e825c1e8bdc..2b82d2d6e78 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/IrBuiltInsOverFir.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/IrBuiltInsOverFir.kt @@ -11,7 +11,9 @@ import org.jetbrains.kotlin.builtins.UnsignedType import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin import org.jetbrains.kotlin.fir.declarations.FirResolvePhase +import org.jetbrains.kotlin.fir.declarations.constructors import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider @@ -125,40 +127,74 @@ class IrBuiltInsOverFir( override val stringClass: IrClassSymbol by lazy { loadClass(StandardClassIds.String) } override val stringType: IrType get() = stringClass.defaultTypeWithoutArguments - internal val intrinsicConst by lazy { - /* - * Old versions of stdlib may not contain @IntrinsicConstEvaluation (AV < 1.7), so in this case we should create annotation class manually - * - * Ideally, we should try to load it from FIR at first, but the thing is that this annotation is used for some generated builtin functions - * (see init section below), so if Fir2IrLazyClass for this annotation is created, it will call for `components.fakeOverrideGenerator`, - * which is not initialized by this moment - * As a possible way to fix it we can move `init` section of builtins into the separate function for late initialization and call - * for it after Fir2IrComponentsStorage is fully initialized - */ - val irClass = createIntrinsicConstEvaluationClass() + private class IntrinsicConstAnnotation(val classSymbol: IrClassSymbol, val annotationCall: IrConstructorCall) + + private val intrinsicConst: IntrinsicConstAnnotation by lazy { val firClassSymbol = session.symbolProvider.getClassLikeSymbolByClassId( StandardClassIds.Annotations.IntrinsicConstEvaluation ) as FirRegularClassSymbol? - if (firClassSymbol != null) { - /* - * If @IntrinsicConstEvaluation is present in dependencies, we should manually cache relation between FIR and IR class - * Without it classifier storage may create another IR class for @IntrinsicConstEvaluation, if it will be referenced - * somewhere in the code - */ - @OptIn(LeakedDeclarationCaches::class) - components.classifierStorage.cacheIrClass(firClassSymbol.fir, irClass) + val (classSymbol, constructorSymbol) = when { + firClassSymbol?.origin == FirDeclarationOrigin.Source -> { + /** + * If @IntrinsicConstEvaluation is present in sources, then we are compiling stdlib and there is no need to create IrClass + * for it manually, as we will create it from the source FIR class + */ + val irClassSymbol = components.classifierStorage.getIrClassSymbol(firClassSymbol) + val firConstructor = firClassSymbol.fir.constructors(session).single() + val irConstructorSymbol = components.declarationStorage.getIrConstructorSymbol(firConstructor, potentiallyExternal = false) + irClassSymbol to irConstructorSymbol + } + + else -> { + /* + * Old versions of stdlib may not contain @IntrinsicConstEvaluation (AV < 1.7), so in this case we should create annotation class manually + * + * Ideally, we should try to load it from FIR at first, but the thing is that this annotation is used for some generated builtin functions + * (see init section below), so if Fir2IrLazyClass for this annotation is created, it will call for `components.fakeOverrideGenerator`, + * which is not initialized by this moment + * As a possible way to fix it we can move `init` section of builtins into the separate function for late initialization and call + * for it after Fir2IrComponentsStorage is fully initialized + */ + val irClass = createIntrinsicConstEvaluationClass() + if (firClassSymbol != null) { + /* + * If @IntrinsicConstEvaluation is present in dependencies, we should manually cache relation between FIR and IR class + * Without it classifier storage may create another IR class for @IntrinsicConstEvaluation, if it will be referenced + * somewhere in the code + */ + @OptIn(LeakedDeclarationCaches::class) + components.classifierStorage.cacheIrClass(firClassSymbol.fir, irClass) + } + // class for intrinsicConst is created manually and it definitely is not a lazy class + @OptIn(UnsafeDuringIrConstructionAPI::class) + val constructor = irClass.constructors.single() + irClass.symbol to constructor.symbol + } } - irClass.symbol + val annotationCall = IrConstructorCallImpl( + startOffset = UNDEFINED_OFFSET, + endOffset = UNDEFINED_OFFSET, + type = IrSimpleTypeImpl( + classifier = classSymbol, + nullability = SimpleTypeNullability.DEFINITELY_NOT_NULL, + arguments = emptyList(), + annotations = emptyList() + ), + constructorSymbol, + typeArgumentsCount = 0, + constructorTypeArgumentsCount = 0, + valueArgumentsCount = 0, + ) + + IntrinsicConstAnnotation(classSymbol, annotationCall) } - private val intrinsicConstAnnotation: IrConstructorCall by lazy { - // class for intrinsicConst is created manually and it definitely is not a lazy class - @OptIn(UnsafeDuringIrConstructionAPI::class) - val constructor = intrinsicConst.constructors.single() - IrConstructorCallImpl.Companion.fromSymbolOwner(intrinsicConst.defaultType, constructor) - } + internal val intrinsicConstSymbol: IrClassSymbol + get() = intrinsicConst.classSymbol + private val intrinsicConstAnnotation: IrConstructorCall + get() = intrinsicConst.annotationCall override val iteratorClass: IrClassSymbol by lazy { loadClass(StandardClassIds.Iterator) } override val arrayClass: IrClassSymbol by lazy { loadClass(StandardClassIds.Array) } diff --git a/compiler/testData/codegen/box/annotations/intrinsicConstEvaluationInSources.kt b/compiler/testData/codegen/box/annotations/intrinsicConstEvaluationInSources.kt index bd031c84423..a65a70cd26f 100644 --- a/compiler/testData/codegen/box/annotations/intrinsicConstEvaluationInSources.kt +++ b/compiler/testData/codegen/box/annotations/intrinsicConstEvaluationInSources.kt @@ -1,5 +1,5 @@ // IGNORE_BACKEND_K1: JS_IR, JS_IR_ES6, WASM, NATIVE -// IGNORE_BACKEND_K2: ANY +// IGNORE_BACKEND_K2: JS_IR, JS_IR_ES6, WASM, NATIVE // non-jvm backends are ignored because of KT-66432 // ISSUE: KT-65415, KT-66432