[FIR2IR] Don't manually create IR for IntrinsicConstEvaluation if not needed

There is no need to create IR class for `@IntrinsicConstEvaluation` manually
  if it is present in sources

^KT-65415 Fixed
This commit is contained in:
Dmitriy Novozhilov
2024-03-07 15:03:16 +02:00
committed by Space Team
parent 7a383373b0
commit 555cf56d6d
4 changed files with 67 additions and 31 deletions
@@ -513,7 +513,7 @@ class Fir2IrDeclarationStorage(
predefinedOrigin: IrDeclarationOrigin? = null, predefinedOrigin: IrDeclarationOrigin? = null,
isLocal: Boolean = false, isLocal: Boolean = false,
): IrConstructor { ): IrConstructor {
val symbol = getIrConstructorSymbol(constructor.symbol, isLocal) val symbol = getIrConstructorSymbol(constructor.symbol, potentiallyExternal = !isLocal)
return callablesGenerator.createIrConstructor( return callablesGenerator.createIrConstructor(
constructor, constructor,
irParent(), irParent(),
@@ -527,13 +527,13 @@ class Fir2IrDeclarationStorage(
constructorCache[constructor] = irConstructorSymbol constructorCache[constructor] = irConstructorSymbol
} }
fun getIrConstructorSymbol(firConstructorSymbol: FirConstructorSymbol, isLocal: Boolean = false): IrConstructorSymbol { fun getIrConstructorSymbol(firConstructorSymbol: FirConstructorSymbol, potentiallyExternal: Boolean = true): IrConstructorSymbol {
val constructor = firConstructorSymbol.fir val constructor = firConstructorSymbol.fir
getCachedIrConstructorSymbol(constructor)?.let { return it } getCachedIrConstructorSymbol(constructor)?.let { return it }
// caching of created constructor is not called here, because `callablesGenerator` calls `cacheIrConstructor` by itself // caching of created constructor is not called here, because `callablesGenerator` calls `cacheIrConstructor` by itself
val symbol = IrConstructorSymbolImpl() val symbol = IrConstructorSymbolImpl()
if (!isLocal) { if (potentiallyExternal) {
val irParent = findIrParent(constructor, fakeOverrideOwnerLookupTag = null) val irParent = findIrParent(constructor, fakeOverrideOwnerLookupTag = null)
val isIntrinsicConstEvaluation = val isIntrinsicConstEvaluation =
constructor.returnTypeRef.coneType.classId == StandardClassIds.Annotations.IntrinsicConstEvaluation constructor.returnTypeRef.coneType.classId == StandardClassIds.Annotations.IntrinsicConstEvaluation
@@ -51,7 +51,7 @@ class Fir2IrTypeConverter(
StandardClassIds.Double to irBuiltIns.doubleClass, StandardClassIds.Double to irBuiltIns.doubleClass,
StandardClassIds.Char to irBuiltIns.charClass, StandardClassIds.Char to irBuiltIns.charClass,
StandardClassIds.Array to irBuiltIns.arrayClass, StandardClassIds.Array to irBuiltIns.arrayClass,
StandardClassIds.Annotations.IntrinsicConstEvaluation to irBuiltIns.intrinsicConst StandardClassIds.Annotations.IntrinsicConstEvaluation to irBuiltIns.intrinsicConstSymbol
) )
} }
@@ -11,7 +11,9 @@ import org.jetbrains.kotlin.builtins.UnsignedType
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fir.FirSession 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.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.constructors
import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor import org.jetbrains.kotlin.fir.descriptors.FirModuleDescriptor
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider 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 stringClass: IrClassSymbol by lazy { loadClass(StandardClassIds.String) }
override val stringType: IrType get() = stringClass.defaultTypeWithoutArguments override val stringType: IrType get() = stringClass.defaultTypeWithoutArguments
internal val intrinsicConst by lazy { private class IntrinsicConstAnnotation(val classSymbol: IrClassSymbol, val annotationCall: IrConstructorCall)
/*
* Old versions of stdlib may not contain @IntrinsicConstEvaluation (AV < 1.7), so in this case we should create annotation class manually private val intrinsicConst: IntrinsicConstAnnotation by lazy {
*
* 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()
val firClassSymbol = session.symbolProvider.getClassLikeSymbolByClassId( val firClassSymbol = session.symbolProvider.getClassLikeSymbolByClassId(
StandardClassIds.Annotations.IntrinsicConstEvaluation StandardClassIds.Annotations.IntrinsicConstEvaluation
) as FirRegularClassSymbol? ) as FirRegularClassSymbol?
if (firClassSymbol != null) { val (classSymbol, constructorSymbol) = when {
/* firClassSymbol?.origin == FirDeclarationOrigin.Source -> {
* 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 * If @IntrinsicConstEvaluation is present in sources, then we are compiling stdlib and there is no need to create IrClass
* somewhere in the code * for it manually, as we will create it from the source FIR class
*/ */
@OptIn(LeakedDeclarationCaches::class) val irClassSymbol = components.classifierStorage.getIrClassSymbol(firClassSymbol)
components.classifierStorage.cacheIrClass(firClassSymbol.fir, irClass) 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 { internal val intrinsicConstSymbol: IrClassSymbol
// class for intrinsicConst is created manually and it definitely is not a lazy class get() = intrinsicConst.classSymbol
@OptIn(UnsafeDuringIrConstructionAPI::class) private val intrinsicConstAnnotation: IrConstructorCall
val constructor = intrinsicConst.constructors.single() get() = intrinsicConst.annotationCall
IrConstructorCallImpl.Companion.fromSymbolOwner(intrinsicConst.defaultType, constructor)
}
override val iteratorClass: IrClassSymbol by lazy { loadClass(StandardClassIds.Iterator) } override val iteratorClass: IrClassSymbol by lazy { loadClass(StandardClassIds.Iterator) }
override val arrayClass: IrClassSymbol by lazy { loadClass(StandardClassIds.Array) } override val arrayClass: IrClassSymbol by lazy { loadClass(StandardClassIds.Array) }
@@ -1,5 +1,5 @@
// IGNORE_BACKEND_K1: JS_IR, JS_IR_ES6, WASM, NATIVE // 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 // non-jvm backends are ignored because of KT-66432
// ISSUE: KT-65415, KT-66432 // ISSUE: KT-65415, KT-66432