From 873a7c6ef18b70fd319320c086440a6b9424a348 Mon Sep 17 00:00:00 2001 From: Ilya Chernikov Date: Tue, 22 Jun 2021 17:15:45 +0200 Subject: [PATCH] FIR: Implement delayed binding of overriddens in the delegated members fixes the problem when overridden symbols on delegated members were build on the incomplete fake overrides leading to the incorrect generation of the function for default parameter and thus to the codegen error (see withDefaultsMultipleFilesOrder test for an example) --- .../kotlin/fir/backend/ConversionUtils.kt | 59 ++++++++++++------ .../kotlin/fir/backend/Fir2IrComponents.kt | 2 + .../fir/backend/Fir2IrComponentsStorage.kt | 2 + .../kotlin/fir/backend/Fir2IrConverter.kt | 6 +- .../fir/backend/Fir2IrDeclarationStorage.kt | 5 +- .../generators/ClassMemberGenerator.kt | 2 + .../generators/DelegatedMemberGenerator.kt | 60 +++++++++++++------ 7 files changed, 92 insertions(+), 44 deletions(-) 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!!)