Fir2Ir: deal with fake overrides in FirIrLinker

This commit is contained in:
Georgy Bronnikov
2022-01-17 12:17:49 +03:00
committed by Alexander Udalov
parent 0ef474a8d3
commit 1c00f731fd
4 changed files with 96 additions and 11 deletions
@@ -1260,7 +1260,7 @@ class Fir2IrDeclarationStorage(
lazyParent: IrDeclarationParent,
declarationOrigin: IrDeclarationOrigin
): IrSimpleFunction {
val symbol = Fir2IrSimpleFunctionSymbol(signature, fir.containerSource)
val symbol = symbolTable.referenceSimpleFunction(signature)
val firFunctionSymbol = fir.symbol
val irFunction = fir.convertWithOffsets { startOffset, endOffset ->
symbolTable.declareSimpleFunction(signature, { symbol }) {
@@ -7,10 +7,14 @@ package org.jetbrains.kotlin.fir.backend
import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolData.SymbolKind
import org.jetbrains.kotlin.backend.common.serialization.kind
import org.jetbrains.kotlin.fir.backend.generators.FakeOverrideGenerator
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.classId
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent
@@ -27,6 +31,7 @@ class FirIrProvider(val fir2IrComponents: Fir2IrComponents) : IrProvider {
private val symbolProvider = fir2IrComponents.session.symbolProvider
private val declarationStorage = fir2IrComponents.declarationStorage
private val classifierStorage = fir2IrComponents.classifierStorage
private val fakeOverrideGenerator = FakeOverrideGenerator(fir2IrComponents, Fir2IrConversionScope())
override fun getDeclaration(symbol: IrSymbol): IrDeclaration? {
val signature = symbol.signature ?: return null
@@ -78,6 +83,7 @@ class FirIrProvider(val fir2IrComponents: Fir2IrComponents) : IrProvider {
firClass = firClass.declarations.singleOrNull { (it as? FirRegularClass)?.name?.asString() == midName } as? FirRegularClass
?: return null
}
val classId = firClass.classId
val scope =
firClass.unsubstitutedScope(fir2IrComponents.session, fir2IrComponents.scopeSession, withForcedTypeCalculator = true)
when (kind) {
@@ -92,18 +98,31 @@ class FirIrProvider(val fir2IrComponents: Fir2IrComponents) : IrProvider {
parent = classifierStorage.getIrClassSymbol(firClass.symbol).owner
}
SymbolKind.FUNCTION_SYMBOL -> {
parent = classifierStorage.getIrClassSymbol(firClass.symbol).owner
val lastName = Name.guessByFirstCharacter(nameSegments.last())
val functions = mutableListOf<FirSimpleFunction>()
scope.processFunctionsByName(lastName) { functions.add(it.fir) }
scope.processFunctionsByName(lastName) { functionSymbol ->
val dispatchReceiverClassId = (functionSymbol.fir.dispatchReceiverType as? ConeClassLikeType)?.lookupTag?.classId
val function = if (dispatchReceiverClassId != null && dispatchReceiverClassId != classId) {
fakeOverrideGenerator.createFirFunctionFakeOverride(firClass, parent, functionSymbol, scope)!!.first
} else functionSymbol.fir
functions.add(function)
}
firCandidates = functions
parent = classifierStorage.getIrClassSymbol(firClass.symbol).owner
}
SymbolKind.PROPERTY_SYMBOL -> {
parent = classifierStorage.getIrClassSymbol(firClass.symbol).owner
val lastName = Name.guessByFirstCharacter(nameSegments.last())
val properties = mutableListOf<FirVariable>()
scope.processPropertiesByName(lastName) { properties.add(it.fir) }
scope.processPropertiesByName(lastName) { propertySymbol ->
propertySymbol as FirPropertySymbol
val dispatchReceiverClassId = (propertySymbol.fir.dispatchReceiverType as? ConeClassLikeType)?.lookupTag?.classId
val property = if (dispatchReceiverClassId != null && dispatchReceiverClassId != classId) {
fakeOverrideGenerator.createFirPropertyFakeOverride(firClass, parent, propertySymbol, scope)!!.first
} else propertySymbol.fir
properties.add(property)
}
firCandidates = properties
parent = classifierStorage.getIrClassSymbol(firClass.symbol).owner
}
else -> {
val lastName = nameSegments.last()
@@ -16,8 +16,6 @@ import org.jetbrains.kotlin.fir.declarations.utils.allowsToHaveFakeOverride
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
import org.jetbrains.kotlin.fir.declarations.utils.visibility
import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.lazy.Fir2IrLazyClass
import org.jetbrains.kotlin.fir.resolve.defaultType
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
@@ -250,6 +248,77 @@ class FakeOverrideGenerator(
result += irDeclaration
}
private inline fun <D : FirCallableDeclaration, reified S : FirCallableSymbol<D>> createFirFakeOverride(
klass: FirClass,
irClass: IrClass,
originalSymbol: S,
createFakeOverrideSymbol: (firDeclaration: D, baseSymbol: S) -> S,
computeDirectOverridden: FirTypeScope.(S) -> List<S>,
scope: FirTypeScope,
): Pair<D, List<S>>? {
val classLookupTag = klass.symbol.toLookupTag()
val originalDeclaration = originalSymbol.fir
val baseSymbol = originalSymbol.unwrapSubstitutionAndIntersectionOverrides() as S
return when {
originalSymbol.shouldHaveComputedBaseSymbolsForClass(classLookupTag) -> {
// Substitution or intersection case
// We have already a FIR declaration for such fake override
originalDeclaration to computeBaseSymbols(
originalSymbol,
computeDirectOverridden,
scope, classLookupTag
)
}
originalDeclaration.allowsToHaveFakeOverrideIn(klass) -> {
// Trivial fake override case
// We've got no relevant declaration in FIR world for such a fake override in current class, thus we're creating it here
val fakeOverrideSymbol = createFakeOverrideSymbol(originalDeclaration, baseSymbol)
declarationStorage.saveFakeOverrideInClass(irClass, originalDeclaration, fakeOverrideSymbol.fir)
classifierStorage.preCacheTypeParameters(originalDeclaration)
fakeOverrideSymbol.fir to listOf(originalSymbol)
}
else -> {
null
}
}
}
fun createFirFunctionFakeOverride(
klass: FirClass,
irClass: IrClass,
originalSymbol: FirNamedFunctionSymbol,
scope: FirTypeScope
) = createFirFakeOverride(
klass, irClass, originalSymbol,
createFakeOverrideSymbol = { firFunction, callableSymbol ->
FirFakeOverrideGenerator.createSubstitutionOverrideFunction(
session, callableSymbol, firFunction,
newDispatchReceiverType = klass.defaultType(),
isExpect = (klass as? FirRegularClass)?.isExpect == true
)
},
computeDirectOverridden = FirTypeScope::getDirectOverriddenFunctions,
scope
)
fun createFirPropertyFakeOverride(
klass: FirClass,
irClass: IrClass,
originalSymbol: FirPropertySymbol,
scope: FirTypeScope
) = createFirFakeOverride(
klass, irClass, originalSymbol,
createFakeOverrideSymbol = { firProperty, callableSymbol ->
FirFakeOverrideGenerator.createSubstitutionOverrideProperty(
session, callableSymbol, firProperty,
newDispatchReceiverType = klass.defaultType(),
isExpect = (klass as? FirRegularClass)?.isExpect == true
)
},
computeDirectOverridden = FirTypeScope::getDirectOverriddenProperties,
scope
)
private inline fun <reified S : FirCallableSymbol<*>> computeBaseSymbols(
symbol: S,
directOverridden: FirTypeScope.(S) -> List<S>,
@@ -13,14 +13,11 @@ import org.jetbrains.kotlin.fir.declarations.FirFunction
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.initialSignatureAttr
import org.jetbrains.kotlin.fir.symbols.Fir2IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.lazy.lazyVar
import org.jetbrains.kotlin.ir.expressions.IrBody
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.DeserializableClass
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
@@ -31,7 +28,7 @@ class Fir2IrLazySimpleFunction(
origin: IrDeclarationOrigin,
override val fir: FirSimpleFunction,
firParent: FirRegularClass?,
symbol: Fir2IrSimpleFunctionSymbol,
symbol: IrSimpleFunctionSymbol,
isFakeOverride: Boolean
) : AbstractFir2IrLazyFunction<FirSimpleFunction>(components, startOffset, endOffset, origin, symbol, isFakeOverride) {
init {