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
This commit is contained in:
Denis Zharkov
2020-08-20 10:43:29 +03:00
parent 8ce9b2d061
commit 7f3f0faa1a
14 changed files with 252 additions and 205 deletions
@@ -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
@@ -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
}
@@ -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
@@ -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<Name> {
@@ -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) {
@@ -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
}
}
@@ -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) {
@@ -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<*>, FirFunctionSymbol<*>>()
private val fakeOverrideConstructors = mutableMapOf<FirConstructorSymbol, FirConstructorSymbol>()
private val fakeOverrideProperties = mutableMapOf<FirPropertySymbol, FirPropertySymbol>()
private val fakeOverrideFields = mutableMapOf<FirFieldSymbol, FirFieldSymbol>()
private val fakeOverrideAccessors = mutableMapOf<FirAccessorSymbol, FirAccessorSymbol>()
private val fakeOverrideVariables = mutableMapOf<FirVariableSymbol<*>, 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 <reified D : FirCallableSymbol<*>> processDirectOverriddenWithBaseScope(
callableSymbol: D,
noinline processor: (D, FirTypeScope) -> ProcessorAction,
processDirectOverriddenCallablesWithBaseScope: FirTypeScope.(D, ((D, FirTypeScope) -> ProcessorAction)) -> ProcessorAction,
fakeOverridesMap: Map<out FirCallableSymbol<*>, 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 ->
@@ -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<Name> = ALL_OPERATORS.keys
@@ -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<FirCallableSymbol<*>, Collection<FirCallableSymbol<*>>> = mutableMapOf()
private val overriddenSymbols: MutableMap<FirCallableSymbol<*>, Collection<MemberWithBaseScope<out FirCallableSymbol<*>>>> = mutableMapOf()
private val intersectionOverrides: MutableMap<FirCallableSymbol<*>, FirCallableSymbol<*>> = mutableMapOf()
private val intersectionOverrides: MutableMap<FirCallableSymbol<*>, MemberWithBaseScope<out FirCallableSymbol<*>>> = 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<FirNamedFunctionSymbol>)
createIntersectionOverride(
mostSpecific,
extractedOverrides as Collection<MemberWithBaseScope<FirNamedFunctionSymbol>>
)
}
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<FirNamedFunctionSymbol>
extractedOverrides: Collection<MemberWithBaseScope<FirNamedFunctionSymbol>>
): 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 <D : FirCallableSymbol<*>> selectMostSpecificMember(overridables: Collection<D>): D {
private fun <D : FirCallableSymbol<*>> selectMostSpecificMember(overridables: Collection<MemberWithBaseScope<D>>): MemberWithBaseScope<D> {
require(overridables.isNotEmpty()) { "Should have at least one overridable symbol" }
if (overridables.size == 1) {
return overridables.first()
}
val candidates: MutableCollection<D> = ArrayList(2)
var transitivelyMostSpecific: D = overridables.first()
val candidates: MutableCollection<MemberWithBaseScope<D>> = ArrayList(2)
var transitivelyMostSpecific: MemberWithBaseScope<D> = 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<ConeKotlinType>()
val type = it.member.fir.returnTypeRef.coneTypeSafe<ConeKotlinType>()
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 <D : FirCallableSymbol<*>> findMemberWithMaxVisibility(members: Collection<D>): D {
private fun <D : FirCallableSymbol<*>> findMemberWithMaxVisibility(members: Collection<MemberWithBaseScope<D>>): MemberWithBaseScope<D> {
assert(members.isNotEmpty())
var member: D? = null
var member: MemberWithBaseScope<D>? = 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 <D : FirCallableSymbol<*>> extractBothWaysOverridable(
overrider: D,
members: MutableCollection<D>
): Collection<D> {
val result = mutableListOf<D>().apply { add(overrider) }
overrider: MemberWithBaseScope<D>,
members: MutableCollection<MemberWithBaseScope<D>>
): Collection<MemberWithBaseScope<D>> {
val result = mutableListOf<MemberWithBaseScope<D>>().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 <S : FirCallableSymbol<*>> getDirectOverriddenSymbols(symbol: S): Collection<S> {
private fun <S : FirCallableSymbol<*>> getDirectOverriddenSymbols(symbol: S): Collection<MemberWithBaseScope<S>> {
val intersectionOverride = intersectionOverrides[symbol]
val allDirectOverridden = overriddenSymbols[symbol].orEmpty() + intersectionOverride?.let {
overriddenSymbols[it]
overriddenSymbols[it.member]
}.orEmpty()
return allDirectOverridden as Collection<S>
return allDirectOverridden as Collection<MemberWithBaseScope<S>>
}
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 <D : FirCallableSymbol<*>> 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<D : FirCallableSymbol<*>>(val member: D, private val baseScope: FirTypeScope) {
operator fun component1() = member
operator fun component2() = baseScope
}
private fun <D : FirCallableSymbol<*>> D.withScope(baseScope: FirTypeScope) = MemberWithBaseScope(this, baseScope)
@@ -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 <S : FirCallableSymbol<*>> doProcessOverriddenCallables(
callableSymbol: S,
processor: (S, Int) -> ProcessorAction,
directOverriddenMap: Map<S, Collection<S>>,
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<Name> = emptySet()
override fun getClassifierNames(): Set<Name> = emptySet()
}
protected companion object {
fun <S : FirCallableSymbol<*>> doProcessDirectOverriddenCallables(
callableSymbol: S,
processor: (S, FirTypeScope) -> ProcessorAction,
directOverriddenMap: Map<S, Collection<S>>,
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 <S : FirCallableSymbol<*>> FirTypeScope.doProcessAllOverriddenCallables(
callableSymbol: S,
processor: (S) -> ProcessorAction,
processDirectOverriddenCallablesWithBaseScope: FirTypeScope.(S, (S, FirTypeScope) -> ProcessorAction) -> ProcessorAction,
visited: MutableSet<S>
): 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)
}
@@ -15,6 +15,8 @@ abstract class FirCallableSymbol<D : FirCallableDeclaration<D>> : AbstractFirBas
open val overriddenSymbol: FirCallableSymbol<D>?
get() = null
open val isIntersectionOverride: Boolean get() = false
}
val FirCallableSymbol<*>.isStatic: Boolean get() = (fir as? FirMemberDeclaration)?.status?.isStatic == true
@@ -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<FirSimpleFunction>(callableId), PossiblyFirFakeOverrideSymbol<FirSimpleFunction, FirNamedFunctionSymbol>
class FirConstructorSymbol(
@@ -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<FirProperty>(callableId), PossiblyFirFakeOverrideSymbol<FirProperty, FirPropertySymbol> {
// 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("<error property>")
}
}
}