K2 IC: refactor and optimize lookup tracking

- encapsulate semantic more into helpers
- allow lazy scopes iteration
- simplify reporting code in tower resolver
- fix some inconsistencies and wrong lookups
- remove redundant lookup recordings
- remove lookup scopes for non-star imports

The commit is a refactoring and doesn't change the behaviour of
neither IC nor CRI. Changes in the lookups are mostly due to the
previous obviously wrong lookups (see changed test data).
This commit is contained in:
Ilya Chernikov
2024-02-27 16:44:39 +01:00
committed by Space Team
parent fe4e0e9c2e
commit a823bfd600
29 changed files with 176 additions and 179 deletions
@@ -476,18 +476,13 @@ private fun Candidate.prepareExpectedType(
getExpectedTypeWithSAMConversion(session, scopeSession, argument, basicExpectedType, context)?.also {
session.lookupTracker?.let { lookupTracker ->
parameter.returnTypeRef.coneType.lowerBoundIfFlexible().classId?.takeIf { !it.isLocal }?.let { classId ->
lookupTracker.recordLookup(
SAM_LOOKUP_NAME,
classId.asString(),
callInfo.callSite.source,
callInfo.containingFile.source
)
lookupTracker.recordLookup(
classId.shortClassName,
classId.packageFqName.asString(),
lookupTracker.recordClassMemberLookup(
SAM_LOOKUP_NAME.asString(),
classId,
callInfo.callSite.source,
callInfo.containingFile.source
)
lookupTracker.recordClassLikeLookup(classId, callInfo.callSite.source, callInfo.containingFile.source)
}
}
}
@@ -33,7 +33,6 @@ import org.jetbrains.kotlin.fir.utils.exceptions.withConeTypeEntry
import org.jetbrains.kotlin.name.StandardClassIds.Annotations.HidesMembers
import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.exceptions.errorWithAttachment
enum class ProcessResult {
@@ -277,17 +276,16 @@ class MemberScopeTowerLevel(
): ProcessResult {
val lookupTracker = session.lookupTracker
return processMembers(info, processor) { consumer ->
withMemberCallLookup(lookupTracker, info) { lookupCtx ->
this.processFunctionsAndConstructorsByName(
info, session, bodyResolveComponents,
ConstructorFilter.OnlyInner,
processor = {
lookupCtx.recordCallableMemberLookup(it)
// WARNING, DO NOT CAST FUNCTIONAL TYPE ITSELF
consumer(it as FirFunctionSymbol<*>)
}
)
}
lookupTracker?.recordCallLookup(info, dispatchReceiverValue.type)
this.processFunctionsAndConstructorsByName(
info, session, bodyResolveComponents,
ConstructorFilter.OnlyInner,
processor = {
lookupTracker?.recordCallableCandidateAsLookup(it, info.callSite.source, info.containingFile.source)
// WARNING, DO NOT CAST FUNCTIONAL TYPE ITSELF
consumer(it as FirFunctionSymbol<*>)
}
)
}
}
@@ -297,12 +295,10 @@ class MemberScopeTowerLevel(
): ProcessResult {
val lookupTracker = session.lookupTracker
return processMembers(info, processor) { consumer ->
withMemberCallLookup(lookupTracker, info) { lookupCtx ->
lookupTracker?.recordCallLookup(info, dispatchReceiverValue.type)
this.processPropertiesByName(info.name) {
lookupCtx.recordCallableMemberLookup(it)
consumer(it)
}
lookupTracker?.recordCallLookup(info, dispatchReceiverValue.type)
this.processPropertiesByName(info.name) {
lookupTracker?.recordCallableCandidateAsLookup(it, info.callSite.source, info.containingFile.source)
consumer(it)
}
}
}
@@ -314,28 +310,6 @@ class MemberScopeTowerLevel(
return ProcessResult.FOUND
}
private inline fun withMemberCallLookup(
lookupTracker: FirLookupTrackerComponent?,
info: CallInfo,
body: (Triple<FirLookupTrackerComponent?, SmartList<String>, CallInfo>) -> Unit
) {
lookupTracker?.recordCallLookup(info, dispatchReceiverValue.type)
val lookupScopes = SmartList<String>()
body(Triple(lookupTracker, lookupScopes, info))
if (lookupScopes.isNotEmpty()) {
lookupTracker?.recordCallLookup(info, lookupScopes)
}
}
private fun Triple<FirLookupTrackerComponent?, SmartList<String>, CallInfo>.recordCallableMemberLookup(callable: FirCallableSymbol<*>) {
first?.run {
recordTypeResolveAsLookup(callable.fir.returnTypeRef, third.callSite.source, third.containingFile.source)
callable.callableId.classId?.takeIf { !it.isLocal }?.let { lookupScope ->
second.add(lookupScope.asFqNameString())
}
}
}
private fun FirCallableSymbol<*>.hasConsistentExtensionReceiver(givenExtensionReceivers: List<FirExpression>): Boolean {
return givenExtensionReceivers.isNotEmpty() == hasExtensionReceiver()
}
@@ -5,17 +5,14 @@
package org.jetbrains.kotlin.fir.resolve.transformers
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.FirFile
import org.jetbrains.kotlin.fir.declarations.FirImport
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.builder.buildResolvedImport
import org.jetbrains.kotlin.fir.lookupTracker
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.providers.FirSymbolProvider
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.fir.withFileAnalysisExceptionWrapping
import org.jetbrains.kotlin.name.FqName
class FirImportResolveProcessor(session: FirSession, scopeSession: ScopeSession) : FirTransformerBasedResolveProcessor(
@@ -61,11 +58,10 @@ open class FirImportResolveTransformer protected constructor(
return transformImportForFqName(fqName, import)
}
val parentFqName = fqName.parent()
currentFile?.let {
session.lookupTracker?.recordLookup(fqName.shortName(), parentFqName.asString(), import.source, it.source)
session.lookupTracker?.recordFqNameLookup(fqName, import.source, it.source)
}
return transformImportForFqName(parentFqName, import)
return transformImportForFqName(fqName.parent(), import)
}
protected open val FqName.isAcceptable: Boolean
@@ -87,8 +87,7 @@ class FirSpecificTypeResolverTransformer(
@OptIn(PrivateForInline::class)
override fun transformTypeRef(typeRef: FirTypeRef, data: ScopeClassDeclaration): FirResolvedTypeRef {
val scopeOwnerLookupNames = data.scopes.flatMap { it.scopeOwnerLookupNames }
session.lookupTracker?.recordTypeLookup(typeRef, scopeOwnerLookupNames, currentFile?.source)
session.lookupTracker?.recordTypeLookup(typeRef, data.scopes.flatMap { it.scopeOwnerLookupNames }, currentFile?.source)
withBareTypes(allowed = false) {
typeRef.transformChildren(this, data)
}
@@ -102,8 +101,7 @@ class FirSpecificTypeResolverTransformer(
data: ScopeClassDeclaration
): FirResolvedTypeRef {
functionTypeRef.transformChildren(this, data)
val scopeOwnerLookupNames = data.scopes.flatMap { it.scopeOwnerLookupNames }
session.lookupTracker?.recordTypeLookup(functionTypeRef, scopeOwnerLookupNames, currentFile?.source)
session.lookupTracker?.recordTypeLookup(functionTypeRef, data.scopes.flatMap { it.scopeOwnerLookupNames }, currentFile?.source)
val resolvedTypeWithDiagnostic = resolveType(functionTypeRef, data)
val resolvedType = resolvedTypeWithDiagnostic.type.takeIfAcceptable()
val diagnostic = resolvedTypeWithDiagnostic.diagnostic
@@ -453,8 +453,8 @@ open class FirSupertypeResolverVisitor(
if (!classLikeDeclaration.isLocalClassOrAnonymousObject()) {
session.lookupTracker?.let {
val fileSource = getFirClassifierContainerFileIfAny(classLikeDeclaration.symbol)?.source
val scopeOwnerLookupNames = scopeDeclaration.scopes.flatMap { scope -> scope.scopeOwnerLookupNames }
for (supertypeRef in supertypeRefs) {
val scopeOwnerLookupNames = scopeDeclaration.scopes.flatMap { scope -> scope.scopeOwnerLookupNames }
it.recordTypeLookup(supertypeRef, scopeOwnerLookupNames, fileSource)
}
}
@@ -255,7 +255,7 @@ abstract class AbstractFirSpecificAnnotationResolveTransformer(
calleeReference: FirSimpleNamedReference,
calleeSymbol: FirEnumEntrySymbol
) {
session.lookupTracker?.recordLookup(
session.lookupTracker?.recordNameLookup(
calleeReference.name,
calleeSymbol.dispatchReceiverType?.classId?.asFqNameString() ?: calleeSymbol.callableId.packageName.asString(),
this.source,