[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
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2020 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.
*/
@@ -31,9 +31,8 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.resolver.AllCandidatesRes
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.errorWithFirSpecificEntries
import org.jetbrains.kotlin.analysis.low.level.api.fir.util.withFirEntry
import org.jetbrains.kotlin.analysis.utils.errors.ExceptionAttachmentBuilder
import org.jetbrains.kotlin.analysis.utils.errors.buildErrorWithAttachment
import org.jetbrains.kotlin.analysis.utils.errors.withPsiEntry
import org.jetbrains.kotlin.analysis.utils.errors.rethrowExceptionWithDetails
import org.jetbrains.kotlin.analysis.utils.errors.withPsiEntry
import org.jetbrains.kotlin.analysis.utils.printer.parentOfType
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClassSymbol
@@ -191,7 +190,10 @@ internal class KtFirCallResolver(
}
}
fun <T> transformErrorReference(call: FirElement, calleeReference: T): KtCallInfo where T : FirNamedReference, T : FirDiagnosticHolder {
fun <T> transformErrorReference(
call: FirElement,
calleeReference: T,
): KtCallInfo where T : FirNamedReference, T : FirDiagnosticHolder {
val diagnostic = calleeReference.diagnostic
val ktDiagnostic = calleeReference.createKtDiagnostic(psi)
@@ -953,7 +955,8 @@ internal class KtFirCallResolver(
return classSymbol.unsubstitutedScope(
analysisSession.useSiteSession,
analysisSession.getScopeSessionFor(analysisSession.useSiteSession),
withForcedTypeCalculator = true
withForcedTypeCalculator = true,
memberRequiredPhase = null,
)
.getConstructors(analysisSession.firSymbolBuilder)
.toList()
@@ -1193,8 +1196,10 @@ internal class KtFirCallResolver(
val scope = unsubstitutedScope(
analysisSession.useSiteSession,
analysisSession.getScopeSessionFor(analysisSession.useSiteSession),
false
false,
memberRequiredPhase = null,
)
var equalsSymbol: FirNamedFunctionSymbol? = null
scope.processFunctionsByName(EQUALS) { equalsSymbolFromScope ->
if (equalsSymbol != null) return@processFunctionsByName
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2020 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.
*/
@@ -89,7 +89,8 @@ internal class KtFirScopeProvider(
fir.unsubstitutedScope(
firSession,
getScopeSession(),
withForcedTypeCalculator = false
withForcedTypeCalculator = false,
memberRequiredPhase = null,
)
}?.applyIf(classSymbol is KtEnumEntrySymbol, ::EnumEntryContainingNamesAwareScope)
?: return getEmptyScope()
@@ -269,16 +270,26 @@ internal class KtFirScopeProvider(
)
}
private fun buildJavaEnhancementDeclaredMemberScope(useSiteSession: FirSession, symbol: FirRegularClassSymbol, scopeSession: ScopeSession): JavaClassDeclaredMembersEnhancementScope {
private fun buildJavaEnhancementDeclaredMemberScope(
useSiteSession: FirSession,
symbol: FirRegularClassSymbol,
scopeSession: ScopeSession,
): JavaClassDeclaredMembersEnhancementScope {
return scopeSession.getOrBuild(symbol, JAVA_ENHANCEMENT_FOR_DECLARED_MEMBER) {
val firJavaClass = symbol.fir
require(firJavaClass is FirJavaClass) {
"${firJavaClass.classId} is expected to be FirJavaClass, but ${firJavaClass::class} found"
}
JavaClassDeclaredMembersEnhancementScope(
useSiteSession,
firJavaClass,
JavaScopeProvider.getUseSiteMemberScope(firJavaClass, useSiteSession, scopeSession)
JavaScopeProvider.getUseSiteMemberScope(
firJavaClass,
useSiteSession,
scopeSession,
memberRequiredPhase = FirResolvePhase.TYPES,
)
)
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2020 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.
*/
@@ -11,20 +11,20 @@ import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirAnonymousObjectSymbol
import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirBackingFieldSymbol
import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirNamedClassOrObjectSymbol
import org.jetbrains.kotlin.analysis.api.fir.symbols.KtFirSymbol
import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
import org.jetbrains.kotlin.analysis.api.symbols.KtCallableSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtClassOrObjectSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbol
import org.jetbrains.kotlin.analysis.api.symbols.KtSymbolOrigin
import org.jetbrains.kotlin.analysis.api.lifetime.KtLifetimeToken
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.superConeTypes
import org.jetbrains.kotlin.fir.scopes.*
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirIntersectionOverrideFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirIntersectionOverridePropertySymbol
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
import org.jetbrains.kotlin.fir.types.toRegularClassSymbol
internal class KtFirSymbolDeclarationOverridesProvider(
@@ -120,8 +120,10 @@ internal class KtFirSymbolDeclarationOverridesProvider(
val firTypeScope = firContainer.unsubstitutedScope(
firSession,
analysisSession.getScopeSessionFor(firSession),
withForcedTypeCalculator = false
withForcedTypeCalculator = false,
memberRequiredPhase = null,
)
firTypeScope.processCallableByName(firCallableDeclaration)
process(firTypeScope, firCallableDeclaration)
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2022 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.
*/
@@ -51,6 +51,7 @@ internal abstract class KtFirMemberSymbolPointer<S : KtSymbol>(
useSiteSession = firSession,
scopeSession = scopeSession,
withForcedTypeCalculator = false,
memberRequiredPhase = null,
)
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2022 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.
*/
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.fir.builder.RawFirBuilder
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirFunction
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.scopes.FirContainingNamesAwareScope
import org.jetbrains.kotlin.fir.scopes.FirScopeProvider
@@ -53,7 +54,12 @@ object KtDeclarationAndFirDeclarationEqualityChecker {
private fun receiverTypeMatch(psi: KtCallableDeclaration, fir: FirCallableDeclaration): Boolean {
if ((fir.receiverParameter != null) != (psi.receiverTypeReference != null)) return false
if (fir.receiverParameter != null && !isTheSameTypes(psi.receiverTypeReference!!, fir.receiverParameter!!.typeRef, isVararg = false)) {
if (fir.receiverParameter != null && !isTheSameTypes(
psi.receiverTypeReference!!,
fir.receiverParameter!!.typeRef,
isVararg = false,
)
) {
return false
}
return true
@@ -249,27 +255,25 @@ object KtDeclarationAndFirDeclarationEqualityChecker {
}
private object DummyScopeProvider : FirScopeProvider() {
override fun getUseSiteMemberScope(klass: FirClass, useSiteSession: FirSession, scopeSession: ScopeSession): FirTypeScope {
shouldNotBeCalled()
}
override fun getUseSiteMemberScope(
klass: FirClass,
useSiteSession: FirSession,
scopeSession: ScopeSession,
memberRequiredPhase: FirResolvePhase?,
): FirTypeScope = shouldNotBeCalled()
override fun getStaticMemberScopeForCallables(
klass: FirClass,
useSiteSession: FirSession,
scopeSession: ScopeSession
): FirContainingNamesAwareScope? {
shouldNotBeCalled()
}
): FirContainingNamesAwareScope? = shouldNotBeCalled()
override fun getNestedClassifierScope(
klass: FirClass,
useSiteSession: FirSession,
scopeSession: ScopeSession
): FirContainingNamesAwareScope? {
shouldNotBeCalled()
}
): FirContainingNamesAwareScope? = shouldNotBeCalled()
private fun shouldNotBeCalled(): Nothing =
error("Should not be called in RawFirBuilder while converting KtTypeReference")
private fun shouldNotBeCalled(): Nothing = error("Should not be called in RawFirBuilder while converting KtTypeReference")
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2020 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.
*/
@@ -46,7 +46,6 @@ abstract class AbstractPartialRawFirBuilderTestCase : AbstractLowLevelApiSingleF
}
}
private fun testFunctionPartialBuilding(ktFile: KtFile, nameToFind: String) {
testPartialBuilding(
ktFile
@@ -97,18 +96,24 @@ abstract class AbstractPartialRawFirBuilderTestCase : AbstractLowLevelApiSingleF
val elementToBuild = findPsiElement(file) as KtDeclaration
val scopeProvider = object : FirScopeProvider() {
override fun getUseSiteMemberScope(klass: FirClass, useSiteSession: FirSession, scopeSession: ScopeSession): FirTypeScope =
error("Should not be called")
override fun getUseSiteMemberScope(
klass: FirClass,
useSiteSession: FirSession,
scopeSession: ScopeSession,
memberRequiredPhase: FirResolvePhase?,
): FirTypeScope = error("Should not be called")
override fun getStaticMemberScopeForCallables(
klass: FirClass,
useSiteSession: FirSession,
scopeSession: ScopeSession
): FirContainingNamesAwareScope? =
error("Should not be called")
scopeSession: ScopeSession,
): FirContainingNamesAwareScope? = error("Should not be called")
override fun getNestedClassifierScope(klass: FirClass, useSiteSession: FirSession, scopeSession: ScopeSession): FirContainingNamesAwareScope? =
error("Should not be called")
override fun getNestedClassifierScope(
klass: FirClass,
useSiteSession: FirSession,
scopeSession: ScopeSession,
): FirContainingNamesAwareScope? = error("Should not be called")
}
val session = FirSessionFactoryHelper.createEmptySession()