FIR: Make qualifier have only one static scope

It's more correct as that's how it works in FE 1.0
This commit is contained in:
Denis Zharkov
2020-06-25 12:52:39 +03:00
parent a017109d7d
commit f3e4e9b162
3 changed files with 16 additions and 84 deletions
@@ -6,24 +6,20 @@
package org.jetbrains.kotlin.fir.resolve.calls package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirTypeAlias
import org.jetbrains.kotlin.fir.declarations.expandedConeType
import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.ScopeSessionKey
import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes
import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.KotlinScopeProvider
import org.jetbrains.kotlin.fir.scopes.impl.FirCompositeScope
import org.jetbrains.kotlin.fir.scopes.impl.FirOnlyCallablesScope import org.jetbrains.kotlin.fir.scopes.impl.FirOnlyCallablesScope
import org.jetbrains.kotlin.fir.scopes.impl.FirOnlyClassifiersScope import org.jetbrains.kotlin.fir.scopes.impl.FirOnlyClassifiersScope
import org.jetbrains.kotlin.fir.scopes.impl.FirPackageMemberScope import org.jetbrains.kotlin.fir.scopes.impl.FirPackageMemberScope
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.ConeClassErrorType
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import java.util.*
fun FirClassLikeDeclaration<*>.fullyExpandedClass(useSiteSession: FirSession): FirRegularClass? { fun FirClassLikeDeclaration<*>.fullyExpandedClass(useSiteSession: FirSession): FirRegularClass? {
@@ -53,7 +49,7 @@ fun createQualifierReceiver(
abstract class QualifierReceiver(final override val explicitReceiver: FirExpression) : AbstractExplicitReceiver<FirResolvedQualifier>() { abstract class QualifierReceiver(final override val explicitReceiver: FirExpression) : AbstractExplicitReceiver<FirResolvedQualifier>() {
abstract fun classifierScope(): FirScope? abstract fun classifierScope(): FirScope?
abstract fun callableScopes(): List<FirScope> abstract fun callableScope(): FirScope?
} }
class ClassQualifierReceiver( class ClassQualifierReceiver(
@@ -64,71 +60,10 @@ class ClassQualifierReceiver(
val scopeSession: ScopeSession val scopeSession: ScopeSession
) : QualifierReceiver(explicitReceiver) { ) : QualifierReceiver(explicitReceiver) {
private companion object { override fun callableScope(): FirScope? {
val SUPERTYPE_STATICS_SCOPE_SESSION_KEY = object : ScopeSessionKey<FirClass<*>, List<FirScope>>() {}
}
private fun collectSuperTypeScopesComposedByDepth(
klass: FirClass<*>,
useSiteSession: FirSession,
scopeSession: ScopeSession,
): List<FirScope> {
val result = mutableListOf<FirScope>()
val provider = klass.scopeProvider
val levelScopes = mutableListOf<FirScope>()
var currentDepth = 1
val queue =
ArrayDeque<Pair<ConeClassLikeType, Int>>()
queue.addAll(
lookupSuperTypes(klass, lookupInterfaces = true, deep = false, useSiteSession = useSiteSession).map { it to 1 },
)
val visitedSymbols = mutableSetOf<FirRegularClassSymbol>()
while (queue.isNotEmpty()) {
val (useSiteSuperType, depth) = queue.poll()
if (depth > currentDepth) {
currentDepth = depth
result += FirCompositeScope(levelScopes.toMutableList())
levelScopes.clear()
}
if (useSiteSuperType is ConeClassErrorType) continue
val superTypeSymbol = useSiteSuperType.lookupTag.toSymbol(useSiteSession) as? FirRegularClassSymbol
?: continue
if (!visitedSymbols.add(superTypeSymbol)) continue
val superTypeScope = provider.getStaticMemberScopeForCallables(
superTypeSymbol.fir, useSiteSession, scopeSession,
)
if (superTypeScope != null) {
levelScopes += superTypeScope
}
queue.addAll(
lookupSuperTypes(
superTypeSymbol.fir, lookupInterfaces = true, deep = false, useSiteSession = useSiteSession,
).map { it to currentDepth + 1 },
)
}
return result
}
private fun getCallableScopes(
useSiteSession: FirSession,
scopeSession: ScopeSession,
): List<FirScope> {
val klass = classSymbol.fir val klass = classSymbol.fir
val result = mutableListOf<FirScope>()
val provider = klass.scopeProvider val provider = klass.scopeProvider
val klassScope = provider.getStaticMemberScopeForCallables(klass, useSiteSession, scopeSession) return provider.getStaticMemberScopeForCallables(klass, useSiteSession, scopeSession)
if (klassScope != null) {
result += klassScope
if (provider is KotlinScopeProvider) return result
result += scopeSession.getOrBuild(klass, SUPERTYPE_STATICS_SCOPE_SESSION_KEY) {
collectSuperTypeScopesComposedByDepth(klass, useSiteSession, scopeSession)
}
}
return result
}
override fun callableScopes(): List<FirScope> {
return getCallableScopes(useSiteSession, scopeSession)
} }
override fun classifierScope(): FirScope? { override fun classifierScope(): FirScope? {
@@ -148,7 +83,5 @@ class PackageQualifierReceiver(
return FirOnlyClassifiersScope(scope) return FirOnlyClassifiersScope(scope)
} }
override fun callableScopes(): List<FirScope> { override fun callableScope() = FirOnlyCallablesScope(scope)
return listOf(FirOnlyCallablesScope(scope))
}
} }
@@ -155,13 +155,12 @@ class FirTowerResolverSession internal constructor(
info: CallInfo, qualifierReceiver: QualifierReceiver? info: CallInfo, qualifierReceiver: QualifierReceiver?
) { ) {
if (qualifierReceiver == null) return if (qualifierReceiver == null) return
for ((depth, qualifierScope) in qualifierReceiver.callableScopes().withIndex()) { val callableScope = qualifierReceiver.callableScope() ?: return
processLevel( processLevel(
qualifierScope.toScopeTowerLevel(includeInnerConstructors = false), callableScope.toScopeTowerLevel(includeInnerConstructors = false),
info.noStubReceiver(), TowerGroup.Qualifier(depth), info.noStubReceiver(), TowerGroup.Qualifier,
useParentGroupForInvokes = true, useParentGroupForInvokes = true,
) )
}
} }
private suspend fun processClassifierScope( private suspend fun processClassifierScope(
@@ -12,7 +12,7 @@ sealed class TowerGroupKind(private val index: Int) : Comparable<TowerGroupKind>
object ClassifierPrioritized : TowerGroupKind(-10) object ClassifierPrioritized : TowerGroupKind(-10)
class Qualifier(depth: Int) : WithDepth(0, depth) object Qualifier : TowerGroupKind(0)
object Classifier : TowerGroupKind(10) object Classifier : TowerGroupKind(10)
@@ -59,7 +59,7 @@ private constructor(
val ClassifierPrioritized = kindOf(TowerGroupKind.ClassifierPrioritized) val ClassifierPrioritized = kindOf(TowerGroupKind.ClassifierPrioritized)
fun Qualifier(depth: Int) = kindOf(TowerGroupKind.Qualifier(depth)) val Qualifier = kindOf(TowerGroupKind.Qualifier)
val Classifier = kindOf(TowerGroupKind.Classifier) val Classifier = kindOf(TowerGroupKind.Classifier)