Filter out inapplicable local scopes in call resolution
The idea is that resolution has an approximate complexity close to (n + n*m) * 3 Where n is a number of scopes, m is a number of receivers and 3-constant is used because each of these combinations runs through 3 processors for functions. And while call resolver seems to be a hot spot, it should be useful to decreate the value of n
This commit is contained in:
+3
-3
@@ -168,10 +168,10 @@ class NewResolutionOldInference(
|
||||
val processor = kind.createTowerProcessor(this, nameToResolve, tracing, scopeTower, detailedReceiver, context)
|
||||
|
||||
if (context.collectAllCandidates) {
|
||||
return allCandidatesResult(towerResolver.collectAllCandidates(scopeTower, processor))
|
||||
return allCandidatesResult(towerResolver.collectAllCandidates(scopeTower, processor, nameToResolve))
|
||||
}
|
||||
|
||||
var candidates = towerResolver.runResolve(scopeTower, processor, useOrder = kind != ResolutionKind.CallableReference)
|
||||
var candidates = towerResolver.runResolve(scopeTower, processor, useOrder = kind != ResolutionKind.CallableReference, name = nameToResolve)
|
||||
|
||||
// Temporary hack to resolve 'rem' as 'mod' if the first is do not present
|
||||
val emptyOrInapplicableCandidates = candidates.isEmpty() ||
|
||||
@@ -179,7 +179,7 @@ class NewResolutionOldInference(
|
||||
if (isBinaryRemOperator && shouldUseOperatorRem && emptyOrInapplicableCandidates) {
|
||||
val deprecatedName = OperatorConventions.REM_TO_MOD_OPERATION_NAMES[name]
|
||||
val processorForDeprecatedName = kind.createTowerProcessor(this, deprecatedName!!, tracing, scopeTower, detailedReceiver, context)
|
||||
candidates = towerResolver.runResolve(scopeTower, processorForDeprecatedName, useOrder = kind != ResolutionKind.CallableReference)
|
||||
candidates = towerResolver.runResolve(scopeTower, processorForDeprecatedName, useOrder = kind != ResolutionKind.CallableReference, name = deprecatedName)
|
||||
}
|
||||
|
||||
if (candidates.isEmpty()) {
|
||||
|
||||
@@ -55,11 +55,11 @@ class KotlinCallResolver(
|
||||
}
|
||||
|
||||
if (collectAllCandidates) {
|
||||
val allCandidates = towerResolver.collectAllCandidates(scopeTower, processor)
|
||||
val allCandidates = towerResolver.collectAllCandidates(scopeTower, processor, kotlinCall.name)
|
||||
return kotlinCallCompleter.createAllCandidatesResult(allCandidates, expectedType, resolutionCallbacks)
|
||||
}
|
||||
|
||||
val candidates = towerResolver.runResolve(scopeTower, processor, useOrder = kotlinCall.callKind != KotlinCallKind.UNSUPPORTED)
|
||||
val candidates = towerResolver.runResolve(scopeTower, processor, useOrder = kotlinCall.callKind != KotlinCallKind.UNSUPPORTED, name = kotlinCall.name)
|
||||
|
||||
return choseMostSpecific(candidateFactory, resolutionCallbacks, expectedType, candidates)
|
||||
}
|
||||
|
||||
+1
-1
@@ -115,7 +115,7 @@ class CallableReferenceResolver(
|
||||
): Set<CallableReferenceCandidate> {
|
||||
val factory = CallableReferencesCandidateFactory(callableReference, callComponents, scopeTower, compatibilityChecker, expectedType)
|
||||
val processor = createCallableReferenceProcessor(factory)
|
||||
val candidates = towerResolver.runResolve(scopeTower, processor, useOrder = true)
|
||||
val candidates = towerResolver.runResolve(scopeTower, processor, useOrder = true, name = callableReference.rhsName)
|
||||
return callableReferenceOverloadConflictResolver.chooseMaximallySpecificCandidates(
|
||||
candidates,
|
||||
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
|
||||
|
||||
@@ -16,12 +16,15 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.tower
|
||||
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
import org.jetbrains.kotlin.resolve.scopes.ImportingScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.ResolutionScope
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
|
||||
import org.jetbrains.kotlin.resolve.scopes.utils.parentsWithSelf
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import java.util.*
|
||||
|
||||
interface Candidate {
|
||||
@@ -74,14 +77,16 @@ class TowerResolver {
|
||||
fun <C: Candidate> runResolve(
|
||||
scopeTower: ImplicitScopeTower,
|
||||
processor: ScopeTowerProcessor<C>,
|
||||
useOrder: Boolean
|
||||
): Collection<C> = scopeTower.run(processor, SuccessfulResultCollector(), useOrder)
|
||||
useOrder: Boolean,
|
||||
name: Name
|
||||
): Collection<C> = scopeTower.run(processor, SuccessfulResultCollector(), useOrder, name)
|
||||
|
||||
fun <C: Candidate> collectAllCandidates(
|
||||
scopeTower: ImplicitScopeTower,
|
||||
processor: ScopeTowerProcessor<C>
|
||||
processor: ScopeTowerProcessor<C>,
|
||||
name: Name
|
||||
): Collection<C>
|
||||
= scopeTower.run(processor, AllCandidatesCollector(), false)
|
||||
= scopeTower.run(processor, AllCandidatesCollector(), false, name)
|
||||
|
||||
private fun ImplicitScopeTower.createNonLocalLevels(): List<ScopeTowerLevel> {
|
||||
val result = ArrayList<ScopeTowerLevel>()
|
||||
@@ -103,14 +108,11 @@ class TowerResolver {
|
||||
private fun <C : Candidate> ImplicitScopeTower.run(
|
||||
processor: ScopeTowerProcessor<C>,
|
||||
resultCollector: ResultCollector<C>,
|
||||
useOrder: Boolean
|
||||
useOrder: Boolean,
|
||||
name: Name
|
||||
): Collection<C> {
|
||||
fun TowerData.process() = processTowerData(processor, resultCollector, useOrder, this)
|
||||
|
||||
val localLevels = lexicalScope.parentsWithSelf.
|
||||
filterIsInstance<LexicalScope>().filter { it.kind.withLocalDescriptors }.
|
||||
map { ScopeBasedTowerLevel(this@run, it) }
|
||||
|
||||
// Lazy calculation
|
||||
var nonLocalLevels: Collection<ScopeTowerLevel>? = null
|
||||
val hidesMembersLevel = HidesMembersTowerLevel(this)
|
||||
@@ -123,6 +125,11 @@ class TowerResolver {
|
||||
// synthetic property for explicit receiver
|
||||
TowerData.TowerLevel(syntheticLevel).process()?.let { return it }
|
||||
|
||||
val localLevels =
|
||||
lexicalScope.parentsWithSelf.
|
||||
filterIsInstance<LexicalScope>().filter { it.kind.withLocalDescriptors && it.mayFitForName(name) }.
|
||||
map { ScopeBasedTowerLevel(this@run, it) }.toList()
|
||||
|
||||
// local non-extensions or extension for explicit receiver
|
||||
for (localLevel in localLevels) {
|
||||
TowerData.TowerLevel(localLevel).process()?.let { return it }
|
||||
@@ -173,6 +180,9 @@ class TowerResolver {
|
||||
return resultCollector.getFinalCandidates()
|
||||
}
|
||||
|
||||
private fun ResolutionScope.mayFitForName(name: Name) =
|
||||
!definitelyDoesNotContainName(name) || !definitelyDoesNotContainName(OperatorNameConventions.INVOKE)
|
||||
|
||||
fun <C : Candidate> runWithEmptyTowerData(
|
||||
processor: ScopeTowerProcessor<C>,
|
||||
resultCollector: ResultCollector<C>,
|
||||
@@ -234,7 +244,7 @@ class TowerResolver {
|
||||
val firstGroupWithResolved = candidateGroups.firstOrNull {
|
||||
it.any { it.resultingApplicability == ResolutionCandidateApplicability.RESOLVED }
|
||||
} ?: return null
|
||||
|
||||
|
||||
return firstGroupWithResolved.filter { it.resultingApplicability == ResolutionCandidateApplicability.RESOLVED }
|
||||
}
|
||||
|
||||
@@ -261,8 +271,8 @@ class TowerResolver {
|
||||
|
||||
return moreSuitableGroup.filter { it.resultingApplicability == groupApplicability }
|
||||
}
|
||||
|
||||
private val Collection<C>.groupApplicability get() =
|
||||
minBy { it.resultingApplicability }?.resultingApplicability ?: ResolutionCandidateApplicability.HIDDEN
|
||||
|
||||
private val Collection<C>.groupApplicability get() =
|
||||
minBy { it.resultingApplicability }?.resultingApplicability ?: ResolutionCandidateApplicability.HIDDEN
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user