[FIR2IR] Get rid of builtin classes scope precaching
Previously it was required to generate fake-overrides for builtin classes beforehead, but during fix of KT-60924 it is no longer required ^KT-60924
This commit is contained in:
committed by
Space Team
parent
4e08cafc78
commit
e31ee1fa57
+12
-42
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.classId
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.visibility
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnonymousObjectExpression
|
||||
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyClass
|
||||
@@ -26,7 +27,6 @@ import org.jetbrains.kotlin.fir.types.toLookupTag
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbolInternals
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
|
||||
@@ -66,42 +66,6 @@ class Fir2IrClassifierStorage(
|
||||
private fun FirTypeRef.toIrType(typeOrigin: ConversionTypeOrigin = ConversionTypeOrigin.DEFAULT): IrType =
|
||||
with(typeConverter) { toIrType(typeOrigin) }
|
||||
|
||||
// ------------------------------------ preprocessing ------------------------------------
|
||||
|
||||
fun preCacheBuiltinClasses() {
|
||||
fun getResolvedClass(classId: ClassId): FirRegularClass? {
|
||||
// toSymbol() can return null when using an old stdlib that's missing some types
|
||||
val firClass = classId.toSymbol(session)?.fir as FirRegularClass? ?: return null
|
||||
|
||||
// Built-in classes may come from sources in the Kotlin project, and so have unresolved types in signatures.
|
||||
// Still, we need return types for all members to make a list of 'IrDeclarations'. Also see 'Fir2IrLazyClass.declarations'.
|
||||
firClass.lazyResolveToPhaseWithCallableMembers(FirResolvePhase.IMPLICIT_TYPES_BODY_RESOLVE)
|
||||
|
||||
return firClass
|
||||
}
|
||||
|
||||
for ((classId, irBuiltinSymbol) in typeConverter.classIdToSymbolMap) {
|
||||
val firClass = getResolvedClass(classId) ?: continue
|
||||
|
||||
@OptIn(IrSymbolInternals::class)
|
||||
val irClass = irBuiltinSymbol.owner
|
||||
classCache[firClass] = irClass
|
||||
classifiersGenerator.processClassHeader(firClass, irClass)
|
||||
declarationStorage.preCacheBuiltinClassMembers(firClass, irClass)
|
||||
}
|
||||
for ((primitiveClassId, primitiveArrayId) in StandardClassIds.primitiveArrayTypeByElementType) {
|
||||
// toSymbol() can return null when using an old stdlib that's missing some types
|
||||
val firClass = getResolvedClass(primitiveArrayId) ?: continue
|
||||
val irType = typeConverter.classIdToTypeMap[primitiveClassId]
|
||||
|
||||
@OptIn(IrSymbolInternals::class)
|
||||
val irClass = irBuiltIns.primitiveArrayForType[irType]!!.owner
|
||||
classCache[firClass] = irClass
|
||||
classifiersGenerator.processClassHeader(firClass, irClass)
|
||||
declarationStorage.preCacheBuiltinClassMembers(firClass, irClass)
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------ type parameters ------------------------------------
|
||||
|
||||
// Note: declareTypeParameters should be called before!
|
||||
@@ -197,11 +161,17 @@ class Fir2IrClassifierStorage(
|
||||
predefinedOrigin: IrDeclarationOrigin? = null
|
||||
): IrClass {
|
||||
return classifiersGenerator.createIrClass(regularClass, parent, predefinedOrigin).also {
|
||||
if (regularClass.visibility == Visibilities.Local) {
|
||||
localStorage[regularClass] = it
|
||||
} else {
|
||||
classCache[regularClass] = it
|
||||
}
|
||||
@OptIn(LeakedDeclarationCaches::class)
|
||||
cacheIrClass(regularClass, it)
|
||||
}
|
||||
}
|
||||
|
||||
@LeakedDeclarationCaches
|
||||
internal fun cacheIrClass(regularClass: FirRegularClass, irClass: IrClass) {
|
||||
if (regularClass.visibility == Visibilities.Local) {
|
||||
localStorage[regularClass] = irClass
|
||||
} else {
|
||||
classCache[regularClass] = irClass
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,15 +65,11 @@ class Fir2IrConverter(
|
||||
private fun runSourcesConversion(
|
||||
allFirFiles: List<FirFile>,
|
||||
irModuleFragment: IrModuleFragmentImpl,
|
||||
fir2irVisitor: Fir2IrVisitor,
|
||||
runPreCacheBuiltinClasses: Boolean
|
||||
fir2irVisitor: Fir2IrVisitor
|
||||
) {
|
||||
for (firFile in allFirFiles) {
|
||||
registerFileAndClasses(firFile, irModuleFragment)
|
||||
}
|
||||
if (runPreCacheBuiltinClasses) {
|
||||
classifierStorage.preCacheBuiltinClasses()
|
||||
}
|
||||
// The file processing is performed phase-to-phase:
|
||||
// 1. Creation of all non-local regular classes
|
||||
// 2. Class header processing (type parameters, supertypes, this receiver)
|
||||
@@ -573,7 +569,9 @@ class Fir2IrConverter(
|
||||
}
|
||||
|
||||
components.converter.runSourcesConversion(
|
||||
allFirFiles, irModuleFragment, components.fir2IrVisitor, runPreCacheBuiltinClasses = initializedIrBuiltIns == null
|
||||
allFirFiles,
|
||||
irModuleFragment,
|
||||
components.fir2IrVisitor
|
||||
)
|
||||
|
||||
if (fir2IrConfiguration.useIrFakeOverrideBuilder) {
|
||||
|
||||
@@ -152,46 +152,6 @@ class Fir2IrDeclarationStorage(
|
||||
|
||||
private val localStorage: Fir2IrLocalCallableStorage by threadLocal { Fir2IrLocalCallableStorage() }
|
||||
|
||||
// ------------------------------------ preprocessing ------------------------------------
|
||||
|
||||
internal fun preCacheBuiltinClassMembers(firClass: FirRegularClass, irClass: IrClass) {
|
||||
for (declaration in firClass.declarations) {
|
||||
when (declaration) {
|
||||
is FirProperty -> {
|
||||
val irProperty = irClass.properties.find { it.name == declaration.name }
|
||||
if (irProperty != null) {
|
||||
propertyCache[declaration] = irProperty
|
||||
}
|
||||
}
|
||||
is FirSimpleFunction -> {
|
||||
val irFunction = irClass.functions.find {
|
||||
areCompatible(declaration, it)
|
||||
}
|
||||
if (irFunction != null) {
|
||||
functionCache[declaration] = irFunction
|
||||
}
|
||||
}
|
||||
is FirConstructor -> {
|
||||
val irConstructor = irClass.constructors.find {
|
||||
areCompatible(declaration, it)
|
||||
}
|
||||
if (irConstructor != null) {
|
||||
constructorCache[declaration] = irConstructor
|
||||
}
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
val scope = firClass.unsubstitutedScope()
|
||||
scope.getCallableNames().forEach { callableName ->
|
||||
buildList {
|
||||
fakeOverrideGenerator.generateFakeOverridesForName(
|
||||
irClass, scope, callableName, firClass, this, realDeclarationSymbols = emptySet()
|
||||
)
|
||||
}.also(fakeOverrideGenerator::bindOverriddenSymbols)
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------ package fragments ------------------------------------
|
||||
|
||||
fun getIrExternalPackageFragment(
|
||||
@@ -1278,34 +1238,6 @@ class Fir2IrDeclarationStorage(
|
||||
)
|
||||
}
|
||||
|
||||
private fun areCompatible(firFunction: FirFunction, irFunction: IrFunction): Boolean {
|
||||
if (firFunction is FirSimpleFunction && irFunction is IrSimpleFunction) {
|
||||
if (irFunction.name != firFunction.name) return false
|
||||
}
|
||||
return irFunction.valueParameters.size == firFunction.valueParameters.size &&
|
||||
irFunction.valueParameters.zip(firFunction.valueParameters).all { (irParameter, firParameter) ->
|
||||
val irType = irParameter.type
|
||||
val firType = firParameter.returnTypeRef.coneType
|
||||
if (irType is IrSimpleType) {
|
||||
when (val irClassifierSymbol = irType.classifier) {
|
||||
is IrTypeParameterSymbol -> {
|
||||
firType is ConeTypeParameterType
|
||||
}
|
||||
is IrClassSymbol -> {
|
||||
@OptIn(IrSymbolInternals::class)
|
||||
val irClass = irClassifierSymbol.owner
|
||||
firType is ConeClassLikeType && irClass.name == firType.lookupTag.name
|
||||
}
|
||||
is IrScriptSymbol -> {
|
||||
false
|
||||
}
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun <reified S : IrSymbol, reified D : IrOverridableDeclaration<S>> ConeClassLookupTagWithFixedSymbol.findIrFakeOverride(
|
||||
name: Name, originalDeclaration: IrOverridableDeclaration<S>
|
||||
): IrSymbol? {
|
||||
|
||||
@@ -129,9 +129,31 @@ class IrBuiltInsOverFir(
|
||||
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
|
||||
/*loadClassSafe(StandardClassIds.Annotations.IntrinsicConstEvaluation) ?: */createIntrinsicConstEvaluationClass().symbol
|
||||
/*
|
||||
* 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()
|
||||
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)
|
||||
}
|
||||
|
||||
irClass.symbol
|
||||
}
|
||||
|
||||
private val intrinsicConstAnnotation: IrConstructorCall by lazy {
|
||||
|
||||
Reference in New Issue
Block a user