FIR2IR: Optimize computation of fake overrides in lazy classes
This commit is contained in:
+3
-2
@@ -866,8 +866,9 @@ class Fir2IrDeclarationStorage(
|
|||||||
irClass: IrClass,
|
irClass: IrClass,
|
||||||
callableDeclaration: FirCallableDeclaration<*>
|
callableDeclaration: FirCallableDeclaration<*>
|
||||||
): FirCallableDeclaration<*>? {
|
): FirCallableDeclaration<*>? {
|
||||||
// Init lazy class if necessary
|
if (irClass is Fir2IrLazyClass) {
|
||||||
irClass.declarations
|
irClass.getFakeOverridesByName(callableDeclaration.symbol.callableId.callableName)
|
||||||
|
}
|
||||||
return fakeOverridesInClass[irClass]?.get(callableDeclaration)
|
return fakeOverridesInClass[irClass]?.get(callableDeclaration)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+83
-50
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.ir.types.*
|
|||||||
import org.jetbrains.kotlin.ir.util.IdSignature
|
import org.jetbrains.kotlin.ir.util.IdSignature
|
||||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||||
import org.jetbrains.kotlin.load.java.JavaDescriptorVisibilities
|
import org.jetbrains.kotlin.load.java.JavaDescriptorVisibilities
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
class FakeOverrideGenerator(
|
class FakeOverrideGenerator(
|
||||||
private val components: Fir2IrComponents,
|
private val components: Fir2IrComponents,
|
||||||
@@ -70,60 +71,86 @@ class FakeOverrideGenerator(
|
|||||||
val useSiteMemberScope = klass.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = true)
|
val useSiteMemberScope = klass.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = true)
|
||||||
val superTypesCallableNames = useSiteMemberScope.getCallableNames()
|
val superTypesCallableNames = useSiteMemberScope.getCallableNames()
|
||||||
val realDeclarationSymbols = realDeclarations.filterIsInstance<FirSymbolOwner<*>>().mapTo(mutableSetOf(), FirSymbolOwner<*>::symbol)
|
val realDeclarationSymbols = realDeclarations.filterIsInstance<FirSymbolOwner<*>>().mapTo(mutableSetOf(), FirSymbolOwner<*>::symbol)
|
||||||
val isLocal = klass !is FirRegularClass || klass.isLocal
|
|
||||||
for (name in superTypesCallableNames) {
|
|
||||||
useSiteMemberScope.processFunctionsByName(name) { functionSymbol ->
|
|
||||||
createFakeOverriddenIfNeeded(
|
|
||||||
klass, this, isLocal, functionSymbol,
|
|
||||||
declarationStorage::getCachedIrFunction,
|
|
||||||
declarationStorage::createIrFunction,
|
|
||||||
createFakeOverrideSymbol = { firFunction, callableSymbol ->
|
|
||||||
FirFakeOverrideGenerator.createSubstitutionOverrideFunction(
|
|
||||||
session, firFunction, callableSymbol,
|
|
||||||
newDispatchReceiverType = klass.defaultType(),
|
|
||||||
derivedClassId = klass.symbol.classId,
|
|
||||||
isExpect = (klass as? FirRegularClass)?.isExpect == true
|
|
||||||
)
|
|
||||||
},
|
|
||||||
baseFunctionSymbols,
|
|
||||||
result,
|
|
||||||
containsErrorTypes = { irFunction ->
|
|
||||||
irFunction.returnType.containsErrorType() || irFunction.valueParameters.any { it.type.containsErrorType() }
|
|
||||||
},
|
|
||||||
realDeclarationSymbols,
|
|
||||||
FirTypeScope::getDirectOverriddenFunctions,
|
|
||||||
useSiteMemberScope,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
useSiteMemberScope.processPropertiesByName(name) { propertySymbol ->
|
for (name in superTypesCallableNames) {
|
||||||
createFakeOverriddenIfNeeded(
|
generateFakeOverridesForName(this, useSiteMemberScope, name, klass, result, realDeclarationSymbols)
|
||||||
klass, this, isLocal, propertySymbol,
|
|
||||||
declarationStorage::getCachedIrProperty,
|
|
||||||
declarationStorage::createIrProperty,
|
|
||||||
createFakeOverrideSymbol = { firProperty, callableSymbol ->
|
|
||||||
FirFakeOverrideGenerator.createSubstitutionOverrideProperty(
|
|
||||||
session, firProperty, callableSymbol,
|
|
||||||
newDispatchReceiverType = klass.defaultType(),
|
|
||||||
derivedClassId = klass.symbol.classId,
|
|
||||||
isExpect = (klass as? FirRegularClass)?.isExpect == true
|
|
||||||
)
|
|
||||||
},
|
|
||||||
basePropertySymbols,
|
|
||||||
result,
|
|
||||||
containsErrorTypes = { irProperty ->
|
|
||||||
irProperty.backingField?.type?.containsErrorType() == true ||
|
|
||||||
irProperty.getter?.returnType?.containsErrorType() == true
|
|
||||||
},
|
|
||||||
realDeclarationSymbols,
|
|
||||||
FirTypeScope::getDirectOverriddenProperties,
|
|
||||||
useSiteMemberScope,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalStdlibApi::class)
|
||||||
|
fun generateFakeOverridesForName(
|
||||||
|
irClass: IrClass,
|
||||||
|
name: Name,
|
||||||
|
firClass: FirClass<*>
|
||||||
|
): List<IrDeclaration> = buildList {
|
||||||
|
val useSiteMemberScope = firClass.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = true)
|
||||||
|
generateFakeOverridesForName(
|
||||||
|
irClass, useSiteMemberScope, name, firClass, this,
|
||||||
|
// This parameter is only needed for data-class methods that is irrelevant for lazy library classes
|
||||||
|
realDeclarationSymbols = emptySet()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateFakeOverridesForName(
|
||||||
|
irClass: IrClass,
|
||||||
|
useSiteMemberScope: FirTypeScope,
|
||||||
|
name: Name,
|
||||||
|
firClass: FirClass<*>,
|
||||||
|
result: MutableList<IrDeclaration>,
|
||||||
|
realDeclarationSymbols: Set<AbstractFirBasedSymbol<*>>
|
||||||
|
) {
|
||||||
|
val isLocal = firClass !is FirRegularClass || firClass.isLocal
|
||||||
|
useSiteMemberScope.processFunctionsByName(name) { functionSymbol ->
|
||||||
|
createFakeOverriddenIfNeeded(
|
||||||
|
firClass, irClass, isLocal, functionSymbol,
|
||||||
|
declarationStorage::getCachedIrFunction,
|
||||||
|
declarationStorage::createIrFunction,
|
||||||
|
createFakeOverrideSymbol = { firFunction, callableSymbol ->
|
||||||
|
FirFakeOverrideGenerator.createSubstitutionOverrideFunction(
|
||||||
|
session, firFunction, callableSymbol,
|
||||||
|
newDispatchReceiverType = firClass.defaultType(),
|
||||||
|
derivedClassId = firClass.symbol.classId,
|
||||||
|
isExpect = (firClass as? FirRegularClass)?.isExpect == true
|
||||||
|
)
|
||||||
|
},
|
||||||
|
baseFunctionSymbols,
|
||||||
|
result,
|
||||||
|
containsErrorTypes = { irFunction ->
|
||||||
|
irFunction.returnType.containsErrorType() || irFunction.valueParameters.any { it.type.containsErrorType() }
|
||||||
|
},
|
||||||
|
realDeclarationSymbols,
|
||||||
|
FirTypeScope::getDirectOverriddenFunctions,
|
||||||
|
useSiteMemberScope,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
useSiteMemberScope.processPropertiesByName(name) { propertySymbol ->
|
||||||
|
createFakeOverriddenIfNeeded(
|
||||||
|
firClass, irClass, isLocal, propertySymbol,
|
||||||
|
declarationStorage::getCachedIrProperty,
|
||||||
|
declarationStorage::createIrProperty,
|
||||||
|
createFakeOverrideSymbol = { firProperty, callableSymbol ->
|
||||||
|
FirFakeOverrideGenerator.createSubstitutionOverrideProperty(
|
||||||
|
session, firProperty, callableSymbol,
|
||||||
|
newDispatchReceiverType = firClass.defaultType(),
|
||||||
|
derivedClassId = firClass.symbol.classId,
|
||||||
|
isExpect = (firClass as? FirRegularClass)?.isExpect == true
|
||||||
|
)
|
||||||
|
},
|
||||||
|
basePropertySymbols,
|
||||||
|
result,
|
||||||
|
containsErrorTypes = { irProperty ->
|
||||||
|
irProperty.backingField?.type?.containsErrorType() == true ||
|
||||||
|
irProperty.getter?.returnType?.containsErrorType() == true
|
||||||
|
},
|
||||||
|
realDeclarationSymbols,
|
||||||
|
FirTypeScope::getDirectOverriddenProperties,
|
||||||
|
useSiteMemberScope,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal fun calcBaseSymbolsForFakeOverrideFunction(
|
internal fun calcBaseSymbolsForFakeOverrideFunction(
|
||||||
klass: FirClass<*>,
|
klass: FirClass<*>,
|
||||||
fakeOverride: IrSimpleFunction,
|
fakeOverride: IrSimpleFunction,
|
||||||
@@ -158,10 +185,16 @@ class FakeOverrideGenerator(
|
|||||||
computeDirectOverridden: FirTypeScope.(S) -> List<S>,
|
computeDirectOverridden: FirTypeScope.(S) -> List<S>,
|
||||||
scope: FirTypeScope,
|
scope: FirTypeScope,
|
||||||
) {
|
) {
|
||||||
if (originalSymbol !is S || originalSymbol in realDeclarationSymbols) return
|
if (originalSymbol !is S) return
|
||||||
val classLookupTag = klass.symbol.toLookupTag()
|
val classLookupTag = klass.symbol.toLookupTag()
|
||||||
val originalDeclaration = originalSymbol.fir
|
val originalDeclaration = originalSymbol.fir
|
||||||
|
|
||||||
if (originalSymbol.dispatchReceiverClassOrNull() == classLookupTag && !originalDeclaration.origin.fromSupertypes) return
|
if (originalSymbol.dispatchReceiverClassOrNull() == classLookupTag && !originalDeclaration.origin.fromSupertypes) return
|
||||||
|
// Data classes' methods from Any (toString/equals/hashCode) are not handled by the line above because they have Any-typed dispatch receiver
|
||||||
|
// (there are no special FIR method for them, it's just fake overrides)
|
||||||
|
// But they are treated differently in IR (real declarations have already been declared before) and such methods are present among realDeclarationSymbols
|
||||||
|
if (originalSymbol in realDeclarationSymbols) return
|
||||||
|
|
||||||
if (originalDeclaration.visibility == Visibilities.Private) return
|
if (originalDeclaration.visibility == Visibilities.Private) return
|
||||||
|
|
||||||
val origin = IrDeclarationOrigin.FAKE_OVERRIDE
|
val origin = IrDeclarationOrigin.FAKE_OVERRIDE
|
||||||
|
|||||||
@@ -117,6 +117,13 @@ class Fir2IrLazyClass(
|
|||||||
receiver
|
receiver
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val fakeOverridesByName = mutableMapOf<Name, Collection<IrDeclaration>>()
|
||||||
|
|
||||||
|
fun getFakeOverridesByName(name: Name): Collection<IrDeclaration> = fakeOverridesByName.getOrPut(name) {
|
||||||
|
fakeOverrideGenerator.generateFakeOverridesForName(this@Fir2IrLazyClass, name, fir)
|
||||||
|
.also(fakeOverrideGenerator::bindOverriddenSymbols)
|
||||||
|
}
|
||||||
|
|
||||||
override val declarations: MutableList<IrDeclaration> by lazyVar {
|
override val declarations: MutableList<IrDeclaration> by lazyVar {
|
||||||
val result = mutableListOf<IrDeclaration>()
|
val result = mutableListOf<IrDeclaration>()
|
||||||
val processedNames = mutableSetOf<Name>()
|
val processedNames = mutableSetOf<Name>()
|
||||||
@@ -166,11 +173,11 @@ class Fir2IrLazyClass(
|
|||||||
else -> continue
|
else -> continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
with(fakeOverrideGenerator) {
|
|
||||||
val fakeOverrides = getFakeOverrides(fir, fir.declarations)
|
for (name in scope.getCallableNames()) {
|
||||||
bindOverriddenSymbols(fakeOverrides)
|
result += getFakeOverridesByName(name)
|
||||||
result += fakeOverrides
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: remove this check to save time
|
// TODO: remove this check to save time
|
||||||
for (declaration in result) {
|
for (declaration in result) {
|
||||||
if (declaration.parent != this) {
|
if (declaration.parent != this) {
|
||||||
|
|||||||
Reference in New Issue
Block a user