diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt index 6cb2fc1438f..7a51698cd11 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt @@ -293,6 +293,24 @@ internal tailrec fun FirCallableSymbol<*>.unwrapCallRepresentative(root: FirCall return overriddenSymbol.unwrapCallRepresentative(this) } +internal fun FirSimpleFunction.processOverriddenFunctionSymbols( + containingClass: FirClass, + session: FirSession, + scopeSession: ScopeSession, + processor: (FirNamedFunctionSymbol) -> Unit +) { + val scope = containingClass.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = true) + scope.processFunctionsByName(name) {} + scope.processOverriddenFunctionsFromSuperClasses(symbol, containingClass) { + if (it.fir.visibility == Visibilities.Private) { + return@processOverriddenFunctionsFromSuperClasses ProcessorAction.NEXT + } + processor(it) + + ProcessorAction.NEXT + } +} + internal fun FirSimpleFunction.generateOverriddenFunctionSymbols( containingClass: FirClass, session: FirSession, @@ -301,20 +319,12 @@ internal fun FirSimpleFunction.generateOverriddenFunctionSymbols( fakeOverrideGenerator: FakeOverrideGenerator, ): List { val superClasses = containingClass.getSuperTypesAsIrClasses(declarationStorage) ?: return emptyList() - - val scope = containingClass.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = true) - scope.processFunctionsByName(name) {} val overriddenSet = mutableSetOf() - scope.processOverriddenFunctionsFromSuperClasses(symbol, containingClass) { - if (it.fir.visibility == Visibilities.Private) { - return@processOverriddenFunctionsFromSuperClasses ProcessorAction.NEXT - } + processOverriddenFunctionSymbols(containingClass, session, scopeSession) { for (overridden in fakeOverrideGenerator.getOverriddenSymbolsInSupertypes(it, superClasses)) { overriddenSet += overridden } - - ProcessorAction.NEXT } return overriddenSet.toList() @@ -353,6 +363,27 @@ private fun FirClass.getSuperTypesAsIrClasses( return irClass.superTypes.mapNotNull { it.classifierOrNull?.owner as? IrClass }.toSet() } +internal fun FirProperty.processOverriddenPropertySymbols( + containingClass: FirClass, + session: FirSession, + scopeSession: ScopeSession, + processor: (FirPropertySymbol) -> Unit +): List { + val scope = containingClass.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = true) + scope.processPropertiesByName(name) {} + val overriddenSet = mutableSetOf() + scope.processOverriddenPropertiesFromSuperClasses(symbol, containingClass) { + if (it.fir.visibility == Visibilities.Private) { + return@processOverriddenPropertiesFromSuperClasses ProcessorAction.NEXT + } + processor(it) + + ProcessorAction.NEXT + } + + return overriddenSet.toList() +} + internal fun FirProperty.generateOverriddenPropertySymbols( containingClass: FirClass, session: FirSession, @@ -361,20 +392,12 @@ internal fun FirProperty.generateOverriddenPropertySymbols( fakeOverrideGenerator: FakeOverrideGenerator, ): List { val superClasses = containingClass.getSuperTypesAsIrClasses(declarationStorage) ?: return emptyList() - - val scope = containingClass.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = true) - scope.processPropertiesByName(name) {} val overriddenSet = mutableSetOf() - scope.processOverriddenPropertiesFromSuperClasses(symbol, containingClass) { - if (it.fir.visibility == Visibilities.Private) { - return@processOverriddenPropertiesFromSuperClasses ProcessorAction.NEXT - } + processOverriddenPropertySymbols(containingClass, session, scopeSession) { for (overridden in fakeOverrideGenerator.getOverriddenSymbolsInSupertypes(it, superClasses)) { overriddenSet += overridden } - - ProcessorAction.NEXT } return overriddenSet.toList() diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponents.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponents.kt index 95fc8199169..444f17be007 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponents.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponents.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.backend import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.backend.generators.AnnotationGenerator import org.jetbrains.kotlin.fir.backend.generators.CallAndReferenceGenerator +import org.jetbrains.kotlin.fir.backend.generators.DelegatedMemberGenerator import org.jetbrains.kotlin.fir.backend.generators.FakeOverrideGenerator import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.ir.IrBuiltIns @@ -35,4 +36,5 @@ interface Fir2IrComponents { val annotationGenerator: AnnotationGenerator val callGenerator: CallAndReferenceGenerator val fakeOverrideGenerator: FakeOverrideGenerator + val delegatedMemberGenerator: DelegatedMemberGenerator } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponentsStorage.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponentsStorage.kt index bd371e1aadf..2b69b3dbde6 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponentsStorage.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrComponentsStorage.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.backend import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.backend.generators.AnnotationGenerator import org.jetbrains.kotlin.fir.backend.generators.CallAndReferenceGenerator +import org.jetbrains.kotlin.fir.backend.generators.DelegatedMemberGenerator import org.jetbrains.kotlin.fir.backend.generators.FakeOverrideGenerator import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.signaturer.FirBasedSignatureComposer @@ -35,6 +36,7 @@ class Fir2IrComponentsStorage( override lateinit var annotationGenerator: AnnotationGenerator override lateinit var callGenerator: CallAndReferenceGenerator override lateinit var fakeOverrideGenerator: FakeOverrideGenerator + override lateinit var delegatedMemberGenerator: DelegatedMemberGenerator override val lock: IrLock get() = symbolTable.lock diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt index 125fcfb1e79..ba0b7ced46d 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/Fir2IrConverter.kt @@ -9,10 +9,7 @@ import org.jetbrains.kotlin.config.AnalysisFlags import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.backend.evaluate.evaluateConstants -import org.jetbrains.kotlin.fir.backend.generators.AnnotationGenerator -import org.jetbrains.kotlin.fir.backend.generators.CallAndReferenceGenerator -import org.jetbrains.kotlin.fir.backend.generators.DataClassMembersGenerator -import org.jetbrains.kotlin.fir.backend.generators.FakeOverrideGenerator +import org.jetbrains.kotlin.fir.backend.generators.* import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.utils.isLocal import org.jetbrains.kotlin.fir.declarations.utils.isSynthetic @@ -270,6 +267,7 @@ class Fir2IrConverter( val components = Fir2IrComponentsStorage(session, scopeSession, symbolTable, irFactory, signatureComposer) val classifierStorage = Fir2IrClassifierStorage(components) components.classifierStorage = classifierStorage + components.delegatedMemberGenerator = DelegatedMemberGenerator(components) val declarationStorage = Fir2IrDeclarationStorage(components, moduleDescriptor) components.declarationStorage = declarationStorage components.visibilityConverter = visibilityConverter 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 140bc064e73..330d11193c2 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 @@ -9,7 +9,6 @@ import org.jetbrains.kotlin.KtNodeTypes import org.jetbrains.kotlin.builtins.StandardNames.BUILT_INS_PACKAGE_FQ_NAMES import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.fir.* -import org.jetbrains.kotlin.fir.backend.generators.DelegatedMemberGenerator import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.builder.buildProperty import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter @@ -104,8 +103,6 @@ class Fir2IrDeclarationStorage( private val localStorage by threadLocal { Fir2IrLocalStorage() } - private val delegatedMemberGenerator = DelegatedMemberGenerator(components) - private fun areCompatible(firFunction: FirFunction, irFunction: IrFunction): Boolean { if (firFunction is FirSimpleFunction && irFunction is IrSimpleFunction) { if (irFunction.name != firFunction.name) return false @@ -891,7 +888,7 @@ class Fir2IrDeclarationStorage( fun createIrFieldAndDelegatedMembers(field: FirField, owner: FirClass, irClass: IrClass): IrField { val irField = createIrField(field, origin = IrDeclarationOrigin.DELEGATE) irField.setAndModifyParent(irClass) - delegatedMemberGenerator.generate(irField, field, owner, irClass) + components.delegatedMemberGenerator.generate(irField, field, owner, irClass) return irField } diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt index fbdf63e1bac..88f3abf4ceb 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/ClassMemberGenerator.kt @@ -58,6 +58,8 @@ internal class ClassMemberGenerator( } } fakeOverrideGenerator.bindOverriddenSymbols(irClass.declarations) + components.delegatedMemberGenerator.bindDelegatedMembersOverriddenSymbols(irClass) + klass.declarations.forEach { declaration -> when { declaration is FirTypeAlias -> { diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DelegatedMemberGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DelegatedMemberGenerator.kt index 81043d34d45..2d19e38a741 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DelegatedMemberGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/DelegatedMemberGenerator.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.scopes.processAllProperties import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrBlockBody @@ -21,6 +22,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl +import org.jetbrains.kotlin.ir.types.classifierOrNull import org.jetbrains.kotlin.ir.types.isNothing import org.jetbrains.kotlin.ir.types.isUnit @@ -31,10 +33,13 @@ import org.jetbrains.kotlin.ir.types.isUnit * methods and properties in the super-interface, and creates corresponding members in the subclass. * TODO: generic super interface types and generic delegated members. */ -internal class DelegatedMemberGenerator( +class DelegatedMemberGenerator( private val components: Fir2IrComponents ) : Fir2IrComponents by components { + private val baseFunctionSymbols = mutableMapOf>() + private val basePropertySymbols = mutableMapOf>() + // Generate delegated members for [subClass]. The synthetic field [irField] has the super interface type. fun generate(irField: IrField, firField: FirField, firSubClass: FirClass, subClass: IrClass) { val subClassLookupTag = firSubClass.symbol.toLookupTag() @@ -82,6 +87,28 @@ internal class DelegatedMemberGenerator( } } + fun bindDelegatedMembersOverriddenSymbols(irClass: IrClass) { + val superClasses by lazy(LazyThreadSafetyMode.NONE) { + irClass.superTypes.mapNotNullTo(mutableSetOf()) { it.classifierOrNull?.owner as? IrClass } + } + for (declaration in irClass.declarations) { + if (declaration.origin != IrDeclarationOrigin.DELEGATED_MEMBER) continue + when (declaration) { + is IrSimpleFunction -> { + declaration.overriddenSymbols = baseFunctionSymbols[declaration]?.flatMap { + fakeOverrideGenerator.getOverriddenSymbolsInSupertypes(it, superClasses) + }?.filter { it.owner != declaration }.orEmpty() + } + is IrProperty -> { + declaration.overriddenSymbols = basePropertySymbols[declaration]?.flatMap { + fakeOverrideGenerator.getOverriddenSymbolsInSupertypes(it, superClasses) + }?.filter { it.owner != declaration }.orEmpty() + } + else -> continue + } + } + } + private fun generateDelegatedFunction( subClass: IrClass, firSubClass: FirClass, @@ -94,15 +121,13 @@ internal class DelegatedMemberGenerator( delegateOverride, subClass, origin = IrDeclarationOrigin.DELEGATED_MEMBER, containingClass = firSubClass.symbol.toLookupTag() ) - delegateFunction.overriddenSymbols = - delegateOverride.generateOverriddenFunctionSymbols( - firSubClass, - session, - scopeSession, - declarationStorage, - fakeOverrideGenerator - ) - .filter { it.owner != delegateFunction } + val baseSymbols = mutableListOf() + // the overridden symbols should be collected only after all fake overrides for all superclases are created and bound to their + // overridden symbols, otherwise in some cases they will be left in inconsistent state leading to the errors in IR + delegateOverride.processOverriddenFunctionSymbols(firSubClass, session, scopeSession) { + baseSymbols.add(it) + } + baseFunctionSymbols[delegateFunction] = baseSymbols annotationGenerator.generate(delegateFunction, delegateOverride) val body = createDelegateBody(irField, delegateFunction, superFunction) @@ -166,14 +191,13 @@ internal class DelegatedMemberGenerator( firDelegateProperty, subClass, origin = IrDeclarationOrigin.DELEGATED_MEMBER, containingClass = firSubClass.symbol.toLookupTag() ) - delegateProperty.overriddenSymbols = - firDelegateProperty.generateOverriddenPropertySymbols( - firSubClass, - session, - scopeSession, - declarationStorage, - fakeOverrideGenerator - ) + // the overridden symbols should be collected only after all fake overrides for all superclases are created and bound to their + // overridden symbols, otherwise in some cases they will be left in inconsistent state leading to the errors in IR + val baseSymbols = mutableListOf() + firDelegateProperty.processOverriddenPropertySymbols(firSubClass, session, scopeSession) { + baseSymbols.add(it) + } + basePropertySymbols[delegateProperty] = baseSymbols annotationGenerator.generate(delegateProperty, firDelegateProperty) delegateProperty.getter!!.body = createDelegateBody(irField, delegateProperty.getter!!, superProperty.getter!!)