[FIR] pre-resolve some scope callables before creating a scope

In a lot of cases, when we want to process the
declaration in scope, it should be resolved to at least TYPES phase.

To avoid doing it manually in all our variety of scopes, we do it when the scope it created.
It was implicitly working manually before as lazy resolve did a lot of extra work
on resolving a declaration it was not supposed to resolve.
Now it's not the case, and we have to explicitly resolve all the declarations we need.

^KT-56543

Co-authored-by: Ilya Kirillov <ilya.kirillov@jetbrains.com>
This commit is contained in:
Dmitrii Gridin
2023-03-22 13:01:27 +01:00
committed by Space Team
parent 23e40693a3
commit 706ff6b61f
46 changed files with 347 additions and 174 deletions
@@ -92,7 +92,7 @@ object OperatorFunctionChecks {
val containingClassSymbol = function.containingClassLookupTag()?.toFirRegularClassSymbol(session) ?: return null
val customEqualsSupported = session.languageVersionSettings.supportsFeature(LanguageFeature.CustomEqualsInValueClasses)
if (function.symbol.overriddenFunctions(containingClassSymbol, session, scopeSession)
if (function.symbol.overriddenFunctions(containingClassSymbol, session, scopeSession, memberRequiredPhase = null)
.any { it.containingClassLookupTag()?.classId == StandardClassIds.Any }
|| (customEqualsSupported && function.isTypedEqualsInValueClass(session))
) {
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -124,7 +124,7 @@ private fun ConeClassLikeType.classScope(
)
}
return fir.scopeForClass(substitutor, useSiteSession, scopeSession, memberOwnerLookupTag)
return fir.scopeForClass(substitutor, useSiteSession, scopeSession, memberOwnerLookupTag, requiredPhase)
}
private fun ConeClassLikeType.obtainFirOfClass(useSiteSession: FirSession, requiredPhase: FirResolvePhase): FirClass? {
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSessionComponent
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.utils.delegateFields
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
import org.jetbrains.kotlin.fir.resolve.*
@@ -20,6 +21,7 @@ import org.jetbrains.kotlin.fir.scopes.impl.*
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhaseWithCallableMembers
import org.jetbrains.kotlin.fir.types.*
class FirKotlinScopeProvider(
@@ -27,19 +29,21 @@ class FirKotlinScopeProvider(
klass: FirClass,
declaredMemberScope: FirContainingNamesAwareScope,
useSiteSession: FirSession,
scopeSession: ScopeSession
) -> FirContainingNamesAwareScope = { _, declaredMemberScope, _, _ -> declaredMemberScope }
scopeSession: ScopeSession,
memberRequiredPhase: FirResolvePhase?,
) -> FirContainingNamesAwareScope = { _, declaredMemberScope, _, _, _ -> declaredMemberScope }
) : FirScopeProvider(), FirSessionComponent {
override fun getUseSiteMemberScope(
klass: FirClass,
useSiteSession: FirSession,
scopeSession: ScopeSession
scopeSession: ScopeSession,
memberRequiredPhase: FirResolvePhase?,
): FirTypeScope {
return scopeSession.getOrBuild(klass.symbol, USE_SITE) {
val declaredScope = useSiteSession.declaredMemberScope(klass)
val decoratedDeclaredMemberScope =
declaredMemberScopeDecorator(klass, declaredScope, useSiteSession, scopeSession).let {
declaredMemberScopeDecorator(klass, declaredScope, useSiteSession, scopeSession, memberRequiredPhase).let {
val delegateFields = klass.delegateFields
if (delegateFields.isEmpty())
it
@@ -50,7 +54,7 @@ class FirKotlinScopeProvider(
val scopes = lookupSuperTypes(
klass, lookupInterfaces = true, deep = false, useSiteSession = useSiteSession, substituteTypes = true
).mapNotNull { useSiteSuperType ->
useSiteSuperType.scopeForSupertype(useSiteSession, scopeSession, klass)
useSiteSuperType.scopeForSupertype(useSiteSession, scopeSession, klass, memberRequiredPhase = memberRequiredPhase)
}
FirClassUseSiteMemberScope(
klass,
@@ -92,9 +96,10 @@ data class ConeSubstitutionScopeKey(
fun FirClass.unsubstitutedScope(
useSiteSession: FirSession,
scopeSession: ScopeSession,
withForcedTypeCalculator: Boolean
withForcedTypeCalculator: Boolean,
memberRequiredPhase: FirResolvePhase?,
): FirTypeScope {
val scope = scopeProvider.getUseSiteMemberScope(this, useSiteSession, scopeSession)
val scope = scopeProvider.getUseSiteMemberScope(this, useSiteSession, scopeSession, memberRequiredPhase)
if (withForcedTypeCalculator) return FirScopeWithFakeOverrideTypeCalculator(scope, FakeOverrideTypeCalculator.Forced)
return scope
}
@@ -102,29 +107,33 @@ fun FirClass.unsubstitutedScope(
fun FirClassSymbol<*>.unsubstitutedScope(
useSiteSession: FirSession,
scopeSession: ScopeSession,
withForcedTypeCalculator: Boolean
withForcedTypeCalculator: Boolean,
memberRequiredPhase: FirResolvePhase?,
): FirTypeScope {
return fir.unsubstitutedScope(useSiteSession, scopeSession, withForcedTypeCalculator)
return fir.unsubstitutedScope(useSiteSession, scopeSession, withForcedTypeCalculator, memberRequiredPhase)
}
fun FirClass.scopeForClass(
substitutor: ConeSubstitutor,
useSiteSession: FirSession,
scopeSession: ScopeSession,
memberOwnerLookupTag: ConeClassLikeLookupTag
memberOwnerLookupTag: ConeClassLikeLookupTag,
memberRequiredPhase: FirResolvePhase?,
): FirTypeScope = scopeForClassImpl(
substitutor, useSiteSession, scopeSession,
skipPrivateMembers = false,
classFirDispatchReceiver = this,
// TODO: why it's always false?
isFromExpectClass = false,
memberOwnerLookupTag = memberOwnerLookupTag
memberOwnerLookupTag = memberOwnerLookupTag,
memberRequiredPhase = memberRequiredPhase,
)
fun ConeKotlinType.scopeForSupertype(
useSiteSession: FirSession,
scopeSession: ScopeSession,
derivedClass: FirClass,
memberRequiredPhase: FirResolvePhase?,
): FirTypeScope? {
if (this !is ConeClassLikeType) return null
if (this is ConeErrorType) return null
@@ -143,7 +152,8 @@ fun ConeKotlinType.scopeForSupertype(
skipPrivateMembers = true,
classFirDispatchReceiver = derivedClass,
isFromExpectClass = (derivedClass as? FirRegularClass)?.isExpect == true,
memberOwnerLookupTag = derivedClass.symbol.toLookupTag()
memberOwnerLookupTag = derivedClass.symbol.toLookupTag(),
memberRequiredPhase = memberRequiredPhase,
)
}
@@ -160,9 +170,14 @@ private fun FirClass.scopeForClassImpl(
skipPrivateMembers: Boolean,
classFirDispatchReceiver: FirClass,
isFromExpectClass: Boolean,
memberOwnerLookupTag: ConeClassLikeLookupTag?
memberOwnerLookupTag: ConeClassLikeLookupTag?,
memberRequiredPhase: FirResolvePhase?,
): FirTypeScope {
val basicScope = unsubstitutedScope(useSiteSession, scopeSession, withForcedTypeCalculator = false)
memberRequiredPhase?.let {
lazyResolveToPhaseWithCallableMembers(it)
}
val basicScope = unsubstitutedScope(useSiteSession, scopeSession, withForcedTypeCalculator = false, memberRequiredPhase)
if (substitutor == ConeSubstitutor.Empty) return basicScope
val key = ConeSubstitutionScopeKey(
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -58,12 +58,14 @@ fun debugCollectOverrides(symbol: FirCallableSymbol<*>, scope: FirTypeScope): Ma
fun FirNamedFunctionSymbol.overriddenFunctions(
containingClass: FirClassSymbol<*>,
session: FirSession,
scopeSession: ScopeSession
scopeSession: ScopeSession,
memberRequiredPhase: FirResolvePhase?,
): List<FirFunctionSymbol<*>> {
val firTypeScope = containingClass.unsubstitutedScope(
session,
scopeSession,
withForcedTypeCalculator = true
withForcedTypeCalculator = true,
memberRequiredPhase = memberRequiredPhase,
)
val overriddenFunctions = mutableListOf<FirFunctionSymbol<*>>()
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -17,6 +17,8 @@ import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.scopes.FirContainingNamesAwareScope
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.coneTypeSafe
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
@@ -35,7 +37,7 @@ abstract class FirAbstractImportingScope(
private fun FirClassSymbol<*>.getStaticsScope(): FirContainingNamesAwareScope? =
if (fir.classKind == ClassKind.OBJECT) {
unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = false)
unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = false, memberRequiredPhase = FirResolvePhase.STATUS)
} else {
fir.scopeProvider.getStaticScope(fir, session, scopeSession)
}
@@ -181,7 +181,8 @@ fun ConeClassLikeType.findBaseInvokeSymbol(session: FirSession, scopeSession: Sc
functionN.unsubstitutedScope(
session,
scopeSession,
withForcedTypeCalculator = false
withForcedTypeCalculator = false,
memberRequiredPhase = null,
).processFunctionsByName(OperatorNameConventions.INVOKE) { functionSymbol ->
baseInvokeSymbol = functionSymbol
return@processFunctionsByName