diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt index 834c32866f3..55e3e568561 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrDeclarationStorage.kt @@ -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 }) { diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/FirIrProvider.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/FirIrProvider.kt index 3123aea7b78..1453515cf60 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/FirIrProvider.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/FirIrProvider.kt @@ -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() - 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() - 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() diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/FakeOverrideGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/FakeOverrideGenerator.kt index 4c3318ae963..f7493484a50 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/FakeOverrideGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/FakeOverrideGenerator.kt @@ -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 > createFirFakeOverride( + klass: FirClass, + irClass: IrClass, + originalSymbol: S, + createFakeOverrideSymbol: (firDeclaration: D, baseSymbol: S) -> S, + computeDirectOverridden: FirTypeScope.(S) -> List, + scope: FirTypeScope, + ): Pair>? { + 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 > computeBaseSymbols( symbol: S, directOverridden: FirTypeScope.(S) -> List, diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazySimpleFunction.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazySimpleFunction.kt index 88a1d37c57e..a755b28969f 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazySimpleFunction.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/lazy/Fir2IrLazySimpleFunction.kt @@ -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(components, startOffset, endOffset, origin, symbol, isFakeOverride) { init {