[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.Visibilities
|
||||||
import org.jetbrains.kotlin.descriptors.Visibility
|
import org.jetbrains.kotlin.descriptors.Visibility
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
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.declarations.utils.visibility
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirAnonymousObjectExpression
|
import org.jetbrains.kotlin.fir.expressions.FirAnonymousObjectExpression
|
||||||
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyClass
|
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.UNDEFINED_OFFSET
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
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.IrTypeParameterSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
|
||||||
@@ -66,42 +66,6 @@ class Fir2IrClassifierStorage(
|
|||||||
private fun FirTypeRef.toIrType(typeOrigin: ConversionTypeOrigin = ConversionTypeOrigin.DEFAULT): IrType =
|
private fun FirTypeRef.toIrType(typeOrigin: ConversionTypeOrigin = ConversionTypeOrigin.DEFAULT): IrType =
|
||||||
with(typeConverter) { toIrType(typeOrigin) }
|
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 ------------------------------------
|
// ------------------------------------ type parameters ------------------------------------
|
||||||
|
|
||||||
// Note: declareTypeParameters should be called before!
|
// Note: declareTypeParameters should be called before!
|
||||||
@@ -197,11 +161,17 @@ class Fir2IrClassifierStorage(
|
|||||||
predefinedOrigin: IrDeclarationOrigin? = null
|
predefinedOrigin: IrDeclarationOrigin? = null
|
||||||
): IrClass {
|
): IrClass {
|
||||||
return classifiersGenerator.createIrClass(regularClass, parent, predefinedOrigin).also {
|
return classifiersGenerator.createIrClass(regularClass, parent, predefinedOrigin).also {
|
||||||
if (regularClass.visibility == Visibilities.Local) {
|
@OptIn(LeakedDeclarationCaches::class)
|
||||||
localStorage[regularClass] = it
|
cacheIrClass(regularClass, it)
|
||||||
} else {
|
}
|
||||||
classCache[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(
|
private fun runSourcesConversion(
|
||||||
allFirFiles: List<FirFile>,
|
allFirFiles: List<FirFile>,
|
||||||
irModuleFragment: IrModuleFragmentImpl,
|
irModuleFragment: IrModuleFragmentImpl,
|
||||||
fir2irVisitor: Fir2IrVisitor,
|
fir2irVisitor: Fir2IrVisitor
|
||||||
runPreCacheBuiltinClasses: Boolean
|
|
||||||
) {
|
) {
|
||||||
for (firFile in allFirFiles) {
|
for (firFile in allFirFiles) {
|
||||||
registerFileAndClasses(firFile, irModuleFragment)
|
registerFileAndClasses(firFile, irModuleFragment)
|
||||||
}
|
}
|
||||||
if (runPreCacheBuiltinClasses) {
|
|
||||||
classifierStorage.preCacheBuiltinClasses()
|
|
||||||
}
|
|
||||||
// The file processing is performed phase-to-phase:
|
// The file processing is performed phase-to-phase:
|
||||||
// 1. Creation of all non-local regular classes
|
// 1. Creation of all non-local regular classes
|
||||||
// 2. Class header processing (type parameters, supertypes, this receiver)
|
// 2. Class header processing (type parameters, supertypes, this receiver)
|
||||||
@@ -573,7 +569,9 @@ class Fir2IrConverter(
|
|||||||
}
|
}
|
||||||
|
|
||||||
components.converter.runSourcesConversion(
|
components.converter.runSourcesConversion(
|
||||||
allFirFiles, irModuleFragment, components.fir2IrVisitor, runPreCacheBuiltinClasses = initializedIrBuiltIns == null
|
allFirFiles,
|
||||||
|
irModuleFragment,
|
||||||
|
components.fir2IrVisitor
|
||||||
)
|
)
|
||||||
|
|
||||||
if (fir2IrConfiguration.useIrFakeOverrideBuilder) {
|
if (fir2IrConfiguration.useIrFakeOverrideBuilder) {
|
||||||
|
|||||||
@@ -152,46 +152,6 @@ class Fir2IrDeclarationStorage(
|
|||||||
|
|
||||||
private val localStorage: Fir2IrLocalCallableStorage by threadLocal { Fir2IrLocalCallableStorage() }
|
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 ------------------------------------
|
// ------------------------------------ package fragments ------------------------------------
|
||||||
|
|
||||||
fun getIrExternalPackageFragment(
|
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(
|
private inline fun <reified S : IrSymbol, reified D : IrOverridableDeclaration<S>> ConeClassLookupTagWithFixedSymbol.findIrFakeOverride(
|
||||||
name: Name, originalDeclaration: IrOverridableDeclaration<S>
|
name: Name, originalDeclaration: IrOverridableDeclaration<S>
|
||||||
): IrSymbol? {
|
): IrSymbol? {
|
||||||
|
|||||||
@@ -129,9 +129,31 @@ class IrBuiltInsOverFir(
|
|||||||
override val stringType: IrType get() = stringClass.defaultTypeWithoutArguments
|
override val stringType: IrType get() = stringClass.defaultTypeWithoutArguments
|
||||||
|
|
||||||
internal val intrinsicConst by lazy {
|
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
|
* 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
|
*
|
||||||
|
* 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 {
|
private val intrinsicConstAnnotation: IrConstructorCall by lazy {
|
||||||
|
|||||||
Reference in New Issue
Block a user