From 7f3f0faa1a83014a2a86650e8a7fbc879b1a2ffa Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Thu, 20 Aug 2020 10:43:29 +0300 Subject: [PATCH] FIR: Rework overridden members processing in FirTypeScope Now, FirTypeScope returns only direct overridden and a base scope where a client might look for deeper overridden It's necessary to make the API fast and simple when only direct overridden are needed At the same time, while this API looks a bit complicated for most of the clients there are simple extension helpers that obtain just the direct or all overridden --- .../fir/analysis/checkers/FirHelpers.kt | 2 +- .../kotlin/fir/backend/ConversionUtils.kt | 4 +- .../generators/ClassMemberGenerator.kt | 4 +- .../JavaClassMembersEnhancementScope.kt | 21 +-- .../kotlin/fir/scopes/jvm/JvmMappedScope.kt | 11 +- .../org/jetbrains/kotlin/fir/SessionUtils.kt | 3 +- .../impl/AbstractFirUseSiteMemberScope.kt | 16 +- .../scopes/impl/FirClassSubstitutionScope.kt | 62 ++++--- .../scopes/impl/FirIntegerLiteralTypeScope.kt | 8 +- .../scopes/impl/FirTypeIntersectionScope.kt | 156 +++++++++-------- .../kotlin/fir/scopes/FirTypeScope.kt | 160 ++++++++++-------- .../fir/symbols/impl/FirCallableSymbol.kt | 2 + .../fir/symbols/impl/FirFunctionSymbol.kt | 3 +- .../fir/symbols/impl/FirVariableSymbol.kt | 5 +- 14 files changed, 252 insertions(+), 205 deletions(-) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt index 0e522bd657a..ef20cc795de 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirHelpers.kt @@ -17,8 +17,8 @@ import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.resolve.firSymbolProvider import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolve.transformers.firClassLike -import org.jetbrains.kotlin.fir.scopes.FirTypeScope import org.jetbrains.kotlin.fir.scopes.ProcessorAction +import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol 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 8a3e20e5017..c6605c1c421 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 @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.calls.SyntheticPropertySymbol import org.jetbrains.kotlin.fir.resolve.providers.FirProvider import org.jetbrains.kotlin.fir.scopes.ProcessorAction +import org.jetbrains.kotlin.fir.scopes.processDirectlyOverriddenFunctions import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope import org.jetbrains.kotlin.fir.symbols.AccessorSymbol import org.jetbrains.kotlin.fir.symbols.Fir2IrClassSymbol @@ -39,7 +40,6 @@ import org.jetbrains.kotlin.ir.expressions.IrConstKind import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin import org.jetbrains.kotlin.ir.expressions.impl.* -import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.impl.IrClassPublicSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl @@ -306,7 +306,7 @@ internal fun FirSimpleFunction.generateOverriddenFunctionSymbols( if ((it.fir as FirSimpleFunction).visibility == Visibilities.PRIVATE) { return@processDirectlyOverriddenFunctions ProcessorAction.NEXT } - val overridden = declarationStorage.getIrFunctionSymbol(it) + val overridden = declarationStorage.getIrFunctionSymbol(it.unwrapSubstitutionOverrides()) overriddenSet += overridden as IrSimpleFunctionSymbol ProcessorAction.NEXT } 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 9b8b36dd48c..1e4ab81281a 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 @@ -16,8 +16,10 @@ import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.scopes.ProcessorAction +import org.jetbrains.kotlin.fir.scopes.processDirectlyOverriddenProperties import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol +import org.jetbrains.kotlin.fir.symbols.impl.unwrapSubstitutionOverrides import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrExpression @@ -269,7 +271,7 @@ internal class ClassMemberGenerator( if (it.fir.visibility == Visibilities.PRIVATE) { return@processDirectlyOverriddenProperties ProcessorAction.NEXT } - val overridden = declarationStorage.getIrPropertyOrFieldSymbol(it) + val overridden = declarationStorage.getIrPropertyOrFieldSymbol(it.unwrapSubstitutionOverrides()) if (overridden is IrPropertySymbol) { val accessorSymbol = if (isGetter) overridden.owner.getter?.symbol diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassMembersEnhancementScope.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassMembersEnhancementScope.kt index e81bff6d9a2..153279fff5d 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassMembersEnhancementScope.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassMembersEnhancementScope.kt @@ -85,20 +85,21 @@ class JavaClassMembersEnhancementScope( } } - override fun processOverriddenFunctionsWithDepth( + override fun processDirectOverriddenFunctionsWithBaseScope( functionSymbol: FirFunctionSymbol<*>, - processor: (FirFunctionSymbol<*>, Int) -> ProcessorAction - ): ProcessorAction = doProcessOverriddenCallables( - functionSymbol, processor, overriddenFunctions, useSiteMemberScope, - FirTypeScope::processOverriddenFunctionsWithDepth - ) + processor: (FirFunctionSymbol<*>, FirTypeScope) -> ProcessorAction + ): ProcessorAction = + doProcessDirectOverriddenCallables( + functionSymbol, processor, overriddenFunctions, useSiteMemberScope, + FirTypeScope::processDirectOverriddenFunctionsWithBaseScope + ) - override fun processOverriddenPropertiesWithDepth( + override fun processDirectOverriddenPropertiesWithBaseScope( propertySymbol: FirPropertySymbol, - processor: (FirPropertySymbol, Int) -> ProcessorAction - ): ProcessorAction = doProcessOverriddenCallables( + processor: (FirPropertySymbol, FirTypeScope) -> ProcessorAction + ): ProcessorAction = doProcessDirectOverriddenCallables( propertySymbol, processor, overriddenProperties, useSiteMemberScope, - FirTypeScope::processOverriddenPropertiesWithDepth + FirTypeScope::processDirectOverriddenPropertiesWithBaseScope ) override fun getCallableNames(): Set { diff --git a/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/scopes/jvm/JvmMappedScope.kt b/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/scopes/jvm/JvmMappedScope.kt index 0ed2d776a1c..23c4dd5ac9c 100644 --- a/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/scopes/jvm/JvmMappedScope.kt +++ b/compiler/fir/jvm/src/org/jetbrains/kotlin/fir/scopes/jvm/JvmMappedScope.kt @@ -34,12 +34,9 @@ class JvmMappedScope( declaredMemberScope.processFunctionsByName(name, processor) } - // JvmMappedScope is basically used as declaration scope but it's being wrapped into substitution scopes where - // a use-site (FirOverrideAwareScope) is expected - // So, we put here a stub implementation - override fun processOverriddenFunctionsWithDepth( + override fun processDirectOverriddenFunctionsWithBaseScope( functionSymbol: FirFunctionSymbol<*>, - processor: (FirFunctionSymbol<*>, Int) -> ProcessorAction + processor: (FirFunctionSymbol<*>, FirTypeScope) -> ProcessorAction ) = ProcessorAction.NONE override fun processDeclaredConstructors(processor: (FirConstructorSymbol) -> Unit) { @@ -65,9 +62,9 @@ class JvmMappedScope( declaredMemberScope.processPropertiesByName(name, processor) } - override fun processOverriddenPropertiesWithDepth( + override fun processDirectOverriddenPropertiesWithBaseScope( propertySymbol: FirPropertySymbol, - processor: (FirPropertySymbol, Int) -> ProcessorAction + processor: (FirPropertySymbol, FirTypeScope) -> ProcessorAction ): ProcessorAction = ProcessorAction.NONE override fun processClassifiersByNameWithSubstitution(name: Name, processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit) { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/SessionUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/SessionUtils.kt index dbc1b009aac..899ba819ecb 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/SessionUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/SessionUtils.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.scopes.FirTypeScope import org.jetbrains.kotlin.fir.scopes.ProcessorAction +import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope import org.jetbrains.kotlin.fir.types.ConeInferenceContext import org.jetbrains.kotlin.fir.types.ConeTypeCheckerContext @@ -47,4 +48,4 @@ fun FirSimpleFunction.lowestVisibilityAmongOverrides( } return visibility -} \ No newline at end of file +} diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/AbstractFirUseSiteMemberScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/AbstractFirUseSiteMemberScope.kt index b561fec3158..0e10d1d590d 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/AbstractFirUseSiteMemberScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/AbstractFirUseSiteMemberScope.kt @@ -101,22 +101,22 @@ abstract class AbstractFirUseSiteMemberScope( return newSymbol } - override fun processOverriddenFunctionsWithDepth( + override fun processDirectOverriddenFunctionsWithBaseScope( functionSymbol: FirFunctionSymbol<*>, - processor: (FirFunctionSymbol<*>, Int) -> ProcessorAction + processor: (FirFunctionSymbol<*>, FirTypeScope) -> ProcessorAction ): ProcessorAction = - doProcessOverriddenCallables( + doProcessDirectOverriddenCallables( functionSymbol, processor, directOverriddenFunctions, superTypesScope, - FirTypeScope::processOverriddenFunctionsWithDepth + FirTypeScope::processDirectOverriddenFunctionsWithBaseScope ) - override fun processOverriddenPropertiesWithDepth( + override fun processDirectOverriddenPropertiesWithBaseScope( propertySymbol: FirPropertySymbol, - processor: (FirPropertySymbol, Int) -> ProcessorAction + processor: (FirPropertySymbol, FirTypeScope) -> ProcessorAction ): ProcessorAction = - doProcessOverriddenCallables( + doProcessDirectOverriddenCallables( propertySymbol, processor, directOverriddenProperties, superTypesScope, - FirTypeScope::processOverriddenPropertiesWithDepth + FirTypeScope::processDirectOverriddenPropertiesWithBaseScope ) override fun processClassifiersByNameWithSubstitution(name: Name, processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit) { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassSubstitutionScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassSubstitutionScope.kt index d5908efdfab..3709ac530d9 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassSubstitutionScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassSubstitutionScope.kt @@ -26,7 +26,6 @@ import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl -import org.jetbrains.kotlin.fir.fakeElement import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name @@ -42,9 +41,7 @@ class FirClassSubstitutionScope( private val fakeOverrideFunctions = mutableMapOf, FirFunctionSymbol<*>>() private val fakeOverrideConstructors = mutableMapOf() - private val fakeOverrideProperties = mutableMapOf() - private val fakeOverrideFields = mutableMapOf() - private val fakeOverrideAccessors = mutableMapOf() + private val fakeOverrideVariables = mutableMapOf, FirVariableSymbol<*>>() constructor( session: FirSession, useSiteMemberScope: FirTypeScope, scopeSession: ScopeSession, @@ -61,35 +58,41 @@ class FirClassSubstitutionScope( return super.processFunctionsByName(name, processor) } - override fun processOverriddenFunctionsWithDepth( + override fun processDirectOverriddenFunctionsWithBaseScope( functionSymbol: FirFunctionSymbol<*>, - processor: (FirFunctionSymbol<*>, Int) -> ProcessorAction + processor: (FirFunctionSymbol<*>, FirTypeScope) -> ProcessorAction + ): ProcessorAction = + processDirectOverriddenWithBaseScope( + functionSymbol, processor, FirTypeScope::processDirectOverriddenFunctionsWithBaseScope, fakeOverrideFunctions + ) + + private inline fun > processDirectOverriddenWithBaseScope( + callableSymbol: D, + noinline processor: (D, FirTypeScope) -> ProcessorAction, + processDirectOverriddenCallablesWithBaseScope: FirTypeScope.(D, ((D, FirTypeScope) -> ProcessorAction)) -> ProcessorAction, + fakeOverridesMap: Map, FirCallableSymbol<*>> ): ProcessorAction { - if (!useSiteMemberScope.processOverriddenFunctionsWithDepth(functionSymbol, processor)) { - return ProcessorAction.STOP - } - val unwrapped = functionSymbol.overriddenSymbol as FirFunctionSymbol<*>? ?: return ProcessorAction.NEXT - if (!processor(unwrapped, 1)) { - return ProcessorAction.STOP - } - return useSiteMemberScope.processOverriddenFunctionsWithDepth(unwrapped) { symbol, depth -> - processor(symbol, depth + 1) - } + val original = (callableSymbol.overriddenSymbol as? D)?.takeIf { it in fakeOverridesMap } + ?: return useSiteMemberScope.processDirectOverriddenCallablesWithBaseScope(callableSymbol, processor) + + if (!processor(original, useSiteMemberScope)) return ProcessorAction.STOP + + return useSiteMemberScope.processDirectOverriddenCallablesWithBaseScope(original, processor) } override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) { return useSiteMemberScope.processPropertiesByName(name) process@{ original -> when (original) { is FirPropertySymbol -> { - val property = fakeOverrideProperties.getOrPut(original) { createFakeOverrideProperty(original) } + val property = fakeOverrideVariables.getOrPut(original) { createFakeOverrideProperty(original) } processor(property) } is FirFieldSymbol -> { - val field = fakeOverrideFields.getOrPut(original) { createFakeOverrideField(original) } + val field = fakeOverrideVariables.getOrPut(original) { createFakeOverrideField(original) } processor(field) } is FirAccessorSymbol -> { - val accessor = fakeOverrideAccessors.getOrPut(original) { createFakeOverrideAccessor(original) } + val accessor = fakeOverrideVariables.getOrPut(original) { createFakeOverrideAccessor(original) } processor(accessor) } else -> { @@ -99,21 +102,14 @@ class FirClassSubstitutionScope( } } - override fun processOverriddenPropertiesWithDepth( + override fun processDirectOverriddenPropertiesWithBaseScope( propertySymbol: FirPropertySymbol, - processor: (FirPropertySymbol, Int) -> ProcessorAction - ): ProcessorAction { - if (!useSiteMemberScope.processOverriddenPropertiesWithDepth(propertySymbol, processor)) { - return ProcessorAction.STOP - } - val unwrapped = propertySymbol.overriddenSymbol ?: return ProcessorAction.NEXT - if (!processor(unwrapped, 1)) { - return ProcessorAction.STOP - } - return useSiteMemberScope.processOverriddenPropertiesWithDepth(unwrapped) { symbol, depth -> - processor(symbol, depth + 1) - } - } + processor: (FirPropertySymbol, FirTypeScope) -> ProcessorAction + ): ProcessorAction = + processDirectOverriddenWithBaseScope( + propertySymbol, processor, FirTypeScope::processDirectOverriddenPropertiesWithBaseScope, + fakeOverrideVariables + ) override fun processClassifiersByNameWithSubstitution(name: Name, processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit) { useSiteMemberScope.processClassifiersByNameWithSubstitution(name) { symbol, substitutor -> diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirIntegerLiteralTypeScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirIntegerLiteralTypeScope.kt index 106e94fda67..138b06d9c73 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirIntegerLiteralTypeScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirIntegerLiteralTypeScope.kt @@ -97,14 +97,14 @@ class FirIntegerLiteralTypeScope(private val session: FirSession, val isUnsigned override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) { } - override fun processOverriddenFunctionsWithDepth( + override fun processDirectOverriddenFunctionsWithBaseScope( functionSymbol: FirFunctionSymbol<*>, - processor: (FirFunctionSymbol<*>, Int) -> ProcessorAction + processor: (FirFunctionSymbol<*>, FirTypeScope) -> ProcessorAction ): ProcessorAction = ProcessorAction.NEXT - override fun processOverriddenPropertiesWithDepth( + override fun processDirectOverriddenPropertiesWithBaseScope( propertySymbol: FirPropertySymbol, - processor: (FirPropertySymbol, Int) -> ProcessorAction + processor: (FirPropertySymbol, FirTypeScope) -> ProcessorAction ): ProcessorAction = ProcessorAction.NEXT override fun getCallableNames(): Set = ALL_OPERATORS.keys diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirTypeIntersectionScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirTypeIntersectionScope.kt index d3c5685f95d..bac947e05d7 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirTypeIntersectionScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirTypeIntersectionScope.kt @@ -17,11 +17,13 @@ import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.FirTypeScope import org.jetbrains.kotlin.fir.scopes.ProcessorAction import org.jetbrains.kotlin.fir.symbols.impl.* -import org.jetbrains.kotlin.fir.types.* +import org.jetbrains.kotlin.fir.types.ConeFlexibleType +import org.jetbrains.kotlin.fir.types.ConeKotlinType +import org.jetbrains.kotlin.fir.types.ConeTypeCheckerContext +import org.jetbrains.kotlin.fir.types.coneTypeSafe import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.types.AbstractTypeChecker import org.jetbrains.kotlin.types.AbstractTypeCheckerContext -import org.jetbrains.kotlin.utils.addToStdlib.flattenTo import java.util.* import kotlin.collections.HashSet @@ -36,9 +38,9 @@ class FirTypeIntersectionScope private constructor( private val typeContext = ConeTypeCheckerContext(isErrorTypeEqualsToAnything = false, isStubTypeEqualsToAnything = false, session) - private val overriddenSymbols: MutableMap, Collection>> = mutableMapOf() + private val overriddenSymbols: MutableMap, Collection>>> = mutableMapOf() - private val intersectionOverrides: MutableMap, FirCallableSymbol<*>> = mutableMapOf() + private val intersectionOverrides: MutableMap, MemberWithBaseScope>> = mutableMapOf() override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> Unit) { if (!processCallablesByName(name, processor, absentFunctions, FirScope::processFunctionsByName)) { @@ -70,7 +72,9 @@ class FirTypeIntersectionScope private constructor( } } - resultForScope.takeIf { it.isNotEmpty() } + resultForScope.takeIf { it.isNotEmpty() }?.let { + scope to it + } } if (membersByScope.isEmpty()) { @@ -78,28 +82,33 @@ class FirTypeIntersectionScope private constructor( return false } - membersByScope.singleOrNull()?.let { members -> + membersByScope.singleOrNull()?.let { (scope, members) -> for (member in members) { - overriddenSymbols[member] = listOf(member) + overriddenSymbols[member] = listOf(MemberWithBaseScope(member, scope)) processor(member) } return false } - val allMembers = membersByScope.flattenTo(LinkedList()) + val allMembersWithScope = membersByScope.flatMapTo(mutableListOf()) { (scope, members) -> + members.map { MemberWithBaseScope(it, scope) } + } - while (allMembers.isNotEmpty()) { - val maxByVisibility = findMemberWithMaxVisibility(allMembers) - val extractedOverrides = extractBothWaysOverridable(maxByVisibility, allMembers) + while (allMembersWithScope.isNotEmpty()) { + val maxByVisibility = findMemberWithMaxVisibility(allMembersWithScope) + val extractedOverrides = extractBothWaysOverridable(maxByVisibility, allMembersWithScope) - val mostSpecific = selectMostSpecificMember(extractedOverrides) + val (mostSpecific, scopeForMostSpecific) = selectMostSpecificMember(extractedOverrides) if (extractedOverrides.size > 1) { val intersectionOverride = intersectionOverrides.getOrPut(mostSpecific) { @Suppress("UNCHECKED_CAST") when (mostSpecific) { is FirNamedFunctionSymbol -> { - createIntersectionOverride(mostSpecific, extractedOverrides as Collection) + createIntersectionOverride( + mostSpecific, + extractedOverrides as Collection> + ) } is FirPropertySymbol -> { createIntersectionOverride(mostSpecific) @@ -107,11 +116,11 @@ class FirTypeIntersectionScope private constructor( else -> { throw IllegalStateException("Should not be here") } - } + }.withScope(scopeForMostSpecific) } - overriddenSymbols[intersectionOverride] = extractedOverrides + overriddenSymbols[intersectionOverride.member] = extractedOverrides @Suppress("UNCHECKED_CAST") - processor(intersectionOverride as D) + processor(intersectionOverride.member as D) } else { overriddenSymbols[mostSpecific] = extractedOverrides processor(mostSpecific) @@ -123,9 +132,15 @@ class FirTypeIntersectionScope private constructor( private fun createIntersectionOverride( mostSpecific: FirNamedFunctionSymbol, - extractedOverrides: Collection + extractedOverrides: Collection> ): FirNamedFunctionSymbol { - val newSymbol = FirNamedFunctionSymbol(mostSpecific.callableId, mostSpecific.isFakeOverride, mostSpecific) + val newSymbol = + FirNamedFunctionSymbol( + mostSpecific.callableId, + mostSpecific.isFakeOverride, + mostSpecific, + isIntersectionOverride = true + ) val mostSpecificFunction = mostSpecific.fir createFunctionCopy(mostSpecific.fir, newSymbol).apply { resolvePhase = mostSpecificFunction.resolvePhase @@ -134,8 +149,8 @@ class FirTypeIntersectionScope private constructor( valueParameters += mostSpecificFunction.valueParameters.mapIndexed { index, mostSpecificParameter -> val overriddenWithDefault = extractedOverrides.firstOrNull { - it.fir.valueParameters.getOrNull(index)?.defaultValue != null - }?.fir + it.member.fir.valueParameters.getOrNull(index)?.defaultValue != null + }?.member?.fir if (overriddenWithDefault == null) { mostSpecificParameter } else { @@ -150,7 +165,7 @@ class FirTypeIntersectionScope private constructor( } private fun createIntersectionOverride(mostSpecific: FirPropertySymbol): FirPropertySymbol { - val newSymbol = FirPropertySymbol(mostSpecific.callableId, mostSpecific.isFakeOverride, mostSpecific) + val newSymbol = FirPropertySymbol(mostSpecific.callableId, mostSpecific.isFakeOverride, mostSpecific, isIntersectionOverride = true) val mostSpecificProperty = mostSpecific.fir createPropertyCopy(mostSpecific.fir, newSymbol).apply { resolvePhase = mostSpecificProperty.resolvePhase @@ -160,21 +175,23 @@ class FirTypeIntersectionScope private constructor( return newSymbol } - private fun > selectMostSpecificMember(overridables: Collection): D { + private fun > selectMostSpecificMember(overridables: Collection>): MemberWithBaseScope { require(overridables.isNotEmpty()) { "Should have at least one overridable symbol" } if (overridables.size == 1) { return overridables.first() } - val candidates: MutableCollection = ArrayList(2) - var transitivelyMostSpecific: D = overridables.first() + val candidates: MutableCollection> = ArrayList(2) + var transitivelyMostSpecific: MemberWithBaseScope = overridables.first() for (candidate in overridables) { - if (overridables.all { isMoreSpecific(candidate, it) }) { + if (overridables.all { isMoreSpecific(candidate.member, it.member) }) { candidates.add(candidate) } - if (isMoreSpecific(candidate, transitivelyMostSpecific) && !isMoreSpecific(transitivelyMostSpecific, candidate)) { + if (isMoreSpecific(candidate.member, transitivelyMostSpecific.member) && + !isMoreSpecific(transitivelyMostSpecific.member, candidate.member) + ) { transitivelyMostSpecific = candidate } } @@ -184,7 +201,7 @@ class FirTypeIntersectionScope private constructor( candidates.size == 1 -> candidates.first() else -> { candidates.firstOrNull { - val type = it.fir.returnTypeRef.coneTypeSafe() + val type = it.member.fir.returnTypeRef.coneTypeSafe() type != null && type !is ConeFlexibleType }?.let { return it } candidates.first() @@ -224,10 +241,10 @@ class FirTypeIntersectionScope private constructor( private fun isTypeMoreSpecific(a: ConeKotlinType, b: ConeKotlinType): Boolean = AbstractTypeChecker.isSubtypeOf(typeContext as AbstractTypeCheckerContext, a, b) - private fun > findMemberWithMaxVisibility(members: Collection): D { + private fun > findMemberWithMaxVisibility(members: Collection>): MemberWithBaseScope { assert(members.isNotEmpty()) - var member: D? = null + var member: MemberWithBaseScope? = null for (candidate in members) { if (member == null) { member = candidate @@ -235,8 +252,8 @@ class FirTypeIntersectionScope private constructor( } val result = Visibilities.compare( - (member.fir as FirCallableMemberDeclaration<*>).status.visibility, - (candidate.fir as FirCallableMemberDeclaration<*>).status.visibility + (member.member.fir as FirCallableMemberDeclaration<*>).status.visibility, + (candidate.member.fir as FirCallableMemberDeclaration<*>).status.visibility ) if (result != null && result < 0) { member = candidate @@ -246,14 +263,14 @@ class FirTypeIntersectionScope private constructor( } private fun > extractBothWaysOverridable( - overrider: D, - members: MutableCollection - ): Collection { - val result = mutableListOf().apply { add(overrider) } + overrider: MemberWithBaseScope, + members: MutableCollection> + ): Collection> { + val result = mutableListOf>().apply { add(overrider) } val iterator = members.iterator() - val overrideCandidate = overrider.fir as FirCallableMemberDeclaration<*> + val overrideCandidate = overrider.member.fir as FirCallableMemberDeclaration<*> while (iterator.hasNext()) { val next = iterator.next() if (next == overrider) { @@ -261,7 +278,7 @@ class FirTypeIntersectionScope private constructor( continue } - if (similarFunctionsOrBothProperties(overrideCandidate, next.fir as FirCallableMemberDeclaration<*>)) { + if (similarFunctionsOrBothProperties(overrideCandidate, next.member.fir as FirCallableMemberDeclaration<*>)) { result.add(next) iterator.remove() } @@ -295,46 +312,42 @@ class FirTypeIntersectionScope private constructor( } @Suppress("UNCHECKED_CAST") - private fun > getDirectOverriddenSymbols(symbol: S): Collection { + private fun > getDirectOverriddenSymbols(symbol: S): Collection> { val intersectionOverride = intersectionOverrides[symbol] val allDirectOverridden = overriddenSymbols[symbol].orEmpty() + intersectionOverride?.let { - overriddenSymbols[it] + overriddenSymbols[it.member] }.orEmpty() - return allDirectOverridden as Collection + return allDirectOverridden as Collection> } - override fun processOverriddenFunctionsWithDepth( + override fun processDirectOverriddenFunctionsWithBaseScope( functionSymbol: FirFunctionSymbol<*>, - processor: (FirFunctionSymbol<*>, Int) -> ProcessorAction - ): ProcessorAction { - for (overridden in getDirectOverriddenSymbols(functionSymbol)) { - val overriddenDepth = if (overridden is FirNamedFunctionSymbol && overridden.overriddenSymbol != null) 0 else 1 - if (!processor(overridden, overriddenDepth)) return ProcessorAction.STOP - // TODO: Preserve the scope where directOverridden came from - for (scope in scopes) { - if (!scope.processOverriddenFunctionsWithDepth(overridden) { symbol, depth -> - processor(symbol, depth + overriddenDepth) - } - ) return ProcessorAction.STOP - } - } + processor: (FirFunctionSymbol<*>, FirTypeScope) -> ProcessorAction + ): ProcessorAction = + processDirectOverriddenCallablesCallablesWithBaseScope( + functionSymbol, processor, + FirTypeScope::processDirectOverriddenFunctionsWithBaseScope + ) - return ProcessorAction.NEXT - } - - override fun processOverriddenPropertiesWithDepth( + override fun processDirectOverriddenPropertiesWithBaseScope( propertySymbol: FirPropertySymbol, - processor: (FirPropertySymbol, Int) -> ProcessorAction + processor: (FirPropertySymbol, FirTypeScope) -> ProcessorAction + ): ProcessorAction = + processDirectOverriddenCallablesCallablesWithBaseScope( + propertySymbol, processor, + FirTypeScope::processDirectOverriddenPropertiesWithBaseScope + ) + + private fun > processDirectOverriddenCallablesCallablesWithBaseScope( + callableSymbol: D, + processor: (D, FirTypeScope) -> ProcessorAction, + processDirectOverriddenInBaseScope: FirTypeScope.(D, ((D, FirTypeScope) -> ProcessorAction)) -> ProcessorAction ): ProcessorAction { - for (overridden in getDirectOverriddenSymbols(propertySymbol)) { - val overriddenDepth = if (overridden.overriddenSymbol != null) 0 else 1 - if (!processor(overridden, overriddenDepth)) return ProcessorAction.STOP - // TODO: Preserve the scope where directOverridden came from - for (scope in scopes) { - if (!scope.processOverriddenPropertiesWithDepth(overridden) { symbol, depth -> - processor(symbol, depth + overriddenDepth) - } - ) return ProcessorAction.STOP + for ((overridden, baseScope) in getDirectOverriddenSymbols(callableSymbol)) { + if (overridden === callableSymbol) { + if (!baseScope.processDirectOverriddenInBaseScope(callableSymbol, processor)) return ProcessorAction.STOP + } else { + if (!processor(overridden, baseScope)) return ProcessorAction.STOP } } @@ -360,3 +373,10 @@ class FirTypeIntersectionScope private constructor( } } } + +private class MemberWithBaseScope>(val member: D, private val baseScope: FirTypeScope) { + operator fun component1() = member + operator fun component2() = baseScope +} + +private fun > D.withScope(baseScope: FirTypeScope) = MemberWithBaseScope(this, baseScope) diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/scopes/FirTypeScope.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/scopes/FirTypeScope.kt index 34aa97d2f90..55b18f9171c 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/scopes/FirTypeScope.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/scopes/FirTypeScope.kt @@ -11,95 +11,121 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.name.Name abstract class FirTypeScope : FirScope(), FirContainingNamesAwareScope { + // If the scope instance is the same as the one from which the symbol was originated, this function supplies + // all direct overridden members (each of them comes a base scope where grand-parents [overridden of this overridden] may be obtained from) + // + // For example: + // + // interface A { fun foo() } + // interface B : A { override fun foo() } + // interface C : B { override fun foo() } + // + // Here, for override C::foo from a scope of C, processor will receiver B::foo and scope for B + // Then, for B::foo from scope for B one may receive override A::foo and scope for A + // // Currently, this function and its property brother both have very weak guarantees // - It may silently do nothing on symbols originated from different scope instance // - It may return the same overridden symbols more then once in case of substitution - // - It doesn't guarantee any specific order in which overridden tree will be traversed - // But if the scope instance is the same as the one from which the symbol was originated, this function will enumarate all members - // of the overridden tree - abstract fun processOverriddenFunctionsWithDepth( + abstract fun processDirectOverriddenFunctionsWithBaseScope( functionSymbol: FirFunctionSymbol<*>, - processor: (FirFunctionSymbol<*>, Int) -> ProcessorAction + processor: (FirFunctionSymbol<*>, FirTypeScope) -> ProcessorAction ): ProcessorAction - inline fun processOverriddenFunctions( - functionSymbol: FirFunctionSymbol<*>, - crossinline processor: (FirFunctionSymbol<*>) -> ProcessorAction - ): ProcessorAction = processOverriddenFunctionsWithDepth(functionSymbol) { symbol, _ -> - processor(symbol) - } - - inline fun processDirectlyOverriddenFunctions( - functionSymbol: FirFunctionSymbol<*>, - crossinline processor: (FirFunctionSymbol<*>) -> ProcessorAction - ): ProcessorAction = processOverriddenFunctionsWithDepth(functionSymbol) { symbol, depth -> - if (depth == 1) { - processor(symbol) - } else { - ProcessorAction.NEXT - } - } - // ------------------------------------------------------------------------------------ - abstract fun processOverriddenPropertiesWithDepth( + abstract fun processDirectOverriddenPropertiesWithBaseScope( propertySymbol: FirPropertySymbol, - processor: (FirPropertySymbol, Int) -> ProcessorAction + processor: (FirPropertySymbol, FirTypeScope) -> ProcessorAction ): ProcessorAction - inline fun processOverriddenProperties( - propertySymbol: FirPropertySymbol, - crossinline processor: (FirPropertySymbol) -> ProcessorAction - ): ProcessorAction = processOverriddenPropertiesWithDepth(propertySymbol) { symbol, _ -> - processor(symbol) - } - - inline fun processDirectlyOverriddenProperties( - propertySymbol: FirPropertySymbol, - crossinline processor: (FirPropertySymbol) -> ProcessorAction - ): ProcessorAction = processOverriddenPropertiesWithDepth(propertySymbol) { symbol, depth -> - if (depth == 1) { - processor(symbol) - } else { - ProcessorAction.NEXT - } - } - // ------------------------------------------------------------------------------------ - // This is just a helper for a common implementation - protected fun > doProcessOverriddenCallables( - callableSymbol: S, - processor: (S, Int) -> ProcessorAction, - directOverriddenMap: Map>, - baseScope: FirTypeScope, - processOverriddenCallablesWithDepth: FirTypeScope.(S, (S, Int) -> ProcessorAction) -> ProcessorAction - ): ProcessorAction { - for (overridden in directOverriddenMap[callableSymbol].orEmpty()) { - val overriddenDepth = if (overridden.overriddenSymbol != null) 0 else 1 - if (!processor(overridden, overriddenDepth)) return ProcessorAction.STOP - if (!baseScope.processOverriddenCallablesWithDepth(overridden) { symbol, depth -> - processor(symbol, depth + overriddenDepth) - } - ) return ProcessorAction.STOP - } - - return baseScope.processOverriddenCallablesWithDepth(callableSymbol, processor) - } - object Empty : FirTypeScope() { - override fun processOverriddenFunctionsWithDepth( + override fun processDirectOverriddenFunctionsWithBaseScope( functionSymbol: FirFunctionSymbol<*>, - processor: (FirFunctionSymbol<*>, Int) -> ProcessorAction + processor: (FirFunctionSymbol<*>, FirTypeScope) -> ProcessorAction ): ProcessorAction = ProcessorAction.NEXT - override fun processOverriddenPropertiesWithDepth( + override fun processDirectOverriddenPropertiesWithBaseScope( propertySymbol: FirPropertySymbol, - processor: (FirPropertySymbol, Int) -> ProcessorAction + processor: (FirPropertySymbol, FirTypeScope) -> ProcessorAction ): ProcessorAction = ProcessorAction.NEXT override fun getCallableNames(): Set = emptySet() override fun getClassifierNames(): Set = emptySet() } + + protected companion object { + fun > doProcessDirectOverriddenCallables( + callableSymbol: S, + processor: (S, FirTypeScope) -> ProcessorAction, + directOverriddenMap: Map>, + baseScope: FirTypeScope, + processDirectOverriddenCallables: FirTypeScope.(S, (S, FirTypeScope) -> ProcessorAction) -> ProcessorAction + ): ProcessorAction { + val directOverridden = directOverriddenMap[callableSymbol]?.takeIf { it.isNotEmpty() } + ?: return baseScope.processDirectOverriddenCallables(callableSymbol, processor) + + for (overridden in directOverridden) { + if (overridden.isIntersectionOverride) { + if (!baseScope.processDirectOverriddenCallables(overridden, processor)) return ProcessorAction.STOP + } + if (!processor(overridden, baseScope)) return ProcessorAction.STOP + } + + return ProcessorAction.NONE + } + } +} + +fun FirTypeScope.processOverriddenFunctions( + functionSymbol: FirFunctionSymbol<*>, + processor: (FirFunctionSymbol<*>) -> ProcessorAction +): ProcessorAction = + doProcessAllOverriddenCallables( + functionSymbol, + processor, + FirTypeScope::processDirectOverriddenFunctionsWithBaseScope, + mutableSetOf() + ) + +fun FirTypeScope.processOverriddenProperties( + propertySymbol: FirPropertySymbol, + processor: (FirPropertySymbol) -> ProcessorAction +): ProcessorAction = + doProcessAllOverriddenCallables( + propertySymbol, + processor, + FirTypeScope::processDirectOverriddenPropertiesWithBaseScope, + mutableSetOf() + ) + + +private fun > FirTypeScope.doProcessAllOverriddenCallables( + callableSymbol: S, + processor: (S) -> ProcessorAction, + processDirectOverriddenCallablesWithBaseScope: FirTypeScope.(S, (S, FirTypeScope) -> ProcessorAction) -> ProcessorAction, + visited: MutableSet +): ProcessorAction { + if (!visited.add(callableSymbol)) return ProcessorAction.NONE + return processDirectOverriddenCallablesWithBaseScope(callableSymbol) { overridden, baseScope -> + if (!processor(overridden)) return@processDirectOverriddenCallablesWithBaseScope ProcessorAction.STOP + + baseScope.doProcessAllOverriddenCallables(overridden, processor, processDirectOverriddenCallablesWithBaseScope, visited) + } +} + +inline fun FirTypeScope.processDirectlyOverriddenFunctions( + functionSymbol: FirFunctionSymbol<*>, + crossinline processor: (FirFunctionSymbol<*>) -> ProcessorAction +): ProcessorAction = processDirectOverriddenFunctionsWithBaseScope(functionSymbol) { overridden, _ -> + processor(overridden) +} + +inline fun FirTypeScope.processDirectlyOverriddenProperties( + propertySymbol: FirPropertySymbol, + crossinline processor: (FirPropertySymbol) -> ProcessorAction +): ProcessorAction = processDirectOverriddenPropertiesWithBaseScope(propertySymbol) { overridden, _ -> + processor(overridden) } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirCallableSymbol.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirCallableSymbol.kt index edb9a480d44..ec45104156c 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirCallableSymbol.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirCallableSymbol.kt @@ -15,6 +15,8 @@ abstract class FirCallableSymbol> : AbstractFirBas open val overriddenSymbol: FirCallableSymbol? get() = null + + open val isIntersectionOverride: Boolean get() = false } val FirCallableSymbol<*>.isStatic: Boolean get() = (fir as? FirMemberDeclaration)?.status?.isStatic == true diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirFunctionSymbol.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirFunctionSymbol.kt index 1013e0dc2e3..857ed082c87 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirFunctionSymbol.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirFunctionSymbol.kt @@ -26,7 +26,8 @@ open class FirNamedFunctionSymbol( callableId: CallableId, override val isFakeOverride: Boolean = false, // Actual for fake override only - override val overriddenSymbol: FirNamedFunctionSymbol? = null + override val overriddenSymbol: FirNamedFunctionSymbol? = null, + override val isIntersectionOverride: Boolean = false, ) : FirFunctionSymbol(callableId), PossiblyFirFakeOverrideSymbol class FirConstructorSymbol( diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirVariableSymbol.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirVariableSymbol.kt index 50e81a356a3..2d776e76ebf 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirVariableSymbol.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/symbols/impl/FirVariableSymbol.kt @@ -25,7 +25,8 @@ open class FirPropertySymbol( callableId: CallableId, override val isFakeOverride: Boolean = false, // Actual for fake override only - override val overriddenSymbol: FirPropertySymbol? = null + override val overriddenSymbol: FirPropertySymbol? = null, + override val isIntersectionOverride: Boolean = false, ) : FirVariableSymbol(callableId), PossiblyFirFakeOverrideSymbol { // TODO: should we use this constructor for local variables? constructor(name: Name) : this(CallableId(name)) @@ -46,4 +47,4 @@ class FirErrorPropertySymbol( companion object { val NAME: Name = Name.special("") } -} \ No newline at end of file +}