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)
|
val processor = kind.createTowerProcessor(this, nameToResolve, tracing, scopeTower, detailedReceiver, context)
|
||||||
|
|
||||||
if (context.collectAllCandidates) {
|
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
|
// Temporary hack to resolve 'rem' as 'mod' if the first is do not present
|
||||||
val emptyOrInapplicableCandidates = candidates.isEmpty() ||
|
val emptyOrInapplicableCandidates = candidates.isEmpty() ||
|
||||||
@@ -179,7 +179,7 @@ class NewResolutionOldInference(
|
|||||||
if (isBinaryRemOperator && shouldUseOperatorRem && emptyOrInapplicableCandidates) {
|
if (isBinaryRemOperator && shouldUseOperatorRem && emptyOrInapplicableCandidates) {
|
||||||
val deprecatedName = OperatorConventions.REM_TO_MOD_OPERATION_NAMES[name]
|
val deprecatedName = OperatorConventions.REM_TO_MOD_OPERATION_NAMES[name]
|
||||||
val processorForDeprecatedName = kind.createTowerProcessor(this, deprecatedName!!, tracing, scopeTower, detailedReceiver, context)
|
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()) {
|
if (candidates.isEmpty()) {
|
||||||
|
|||||||
@@ -55,11 +55,11 @@ class KotlinCallResolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (collectAllCandidates) {
|
if (collectAllCandidates) {
|
||||||
val allCandidates = towerResolver.collectAllCandidates(scopeTower, processor)
|
val allCandidates = towerResolver.collectAllCandidates(scopeTower, processor, kotlinCall.name)
|
||||||
return kotlinCallCompleter.createAllCandidatesResult(allCandidates, expectedType, resolutionCallbacks)
|
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)
|
return choseMostSpecific(candidateFactory, resolutionCallbacks, expectedType, candidates)
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -115,7 +115,7 @@ class CallableReferenceResolver(
|
|||||||
): Set<CallableReferenceCandidate> {
|
): Set<CallableReferenceCandidate> {
|
||||||
val factory = CallableReferencesCandidateFactory(callableReference, callComponents, scopeTower, compatibilityChecker, expectedType)
|
val factory = CallableReferencesCandidateFactory(callableReference, callComponents, scopeTower, compatibilityChecker, expectedType)
|
||||||
val processor = createCallableReferenceProcessor(factory)
|
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(
|
return callableReferenceOverloadConflictResolver.chooseMaximallySpecificCandidates(
|
||||||
candidates,
|
candidates,
|
||||||
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
|
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
|
||||||
|
|||||||
@@ -16,12 +16,15 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.resolve.calls.tower
|
package org.jetbrains.kotlin.resolve.calls.tower
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
|
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
|
||||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||||
import org.jetbrains.kotlin.resolve.scopes.ImportingScope
|
import org.jetbrains.kotlin.resolve.scopes.ImportingScope
|
||||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
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.receivers.ReceiverValueWithSmartCastInfo
|
||||||
import org.jetbrains.kotlin.resolve.scopes.utils.parentsWithSelf
|
import org.jetbrains.kotlin.resolve.scopes.utils.parentsWithSelf
|
||||||
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
interface Candidate {
|
interface Candidate {
|
||||||
@@ -74,14 +77,16 @@ class TowerResolver {
|
|||||||
fun <C: Candidate> runResolve(
|
fun <C: Candidate> runResolve(
|
||||||
scopeTower: ImplicitScopeTower,
|
scopeTower: ImplicitScopeTower,
|
||||||
processor: ScopeTowerProcessor<C>,
|
processor: ScopeTowerProcessor<C>,
|
||||||
useOrder: Boolean
|
useOrder: Boolean,
|
||||||
): Collection<C> = scopeTower.run(processor, SuccessfulResultCollector(), useOrder)
|
name: Name
|
||||||
|
): Collection<C> = scopeTower.run(processor, SuccessfulResultCollector(), useOrder, name)
|
||||||
|
|
||||||
fun <C: Candidate> collectAllCandidates(
|
fun <C: Candidate> collectAllCandidates(
|
||||||
scopeTower: ImplicitScopeTower,
|
scopeTower: ImplicitScopeTower,
|
||||||
processor: ScopeTowerProcessor<C>
|
processor: ScopeTowerProcessor<C>,
|
||||||
|
name: Name
|
||||||
): Collection<C>
|
): Collection<C>
|
||||||
= scopeTower.run(processor, AllCandidatesCollector(), false)
|
= scopeTower.run(processor, AllCandidatesCollector(), false, name)
|
||||||
|
|
||||||
private fun ImplicitScopeTower.createNonLocalLevels(): List<ScopeTowerLevel> {
|
private fun ImplicitScopeTower.createNonLocalLevels(): List<ScopeTowerLevel> {
|
||||||
val result = ArrayList<ScopeTowerLevel>()
|
val result = ArrayList<ScopeTowerLevel>()
|
||||||
@@ -103,14 +108,11 @@ class TowerResolver {
|
|||||||
private fun <C : Candidate> ImplicitScopeTower.run(
|
private fun <C : Candidate> ImplicitScopeTower.run(
|
||||||
processor: ScopeTowerProcessor<C>,
|
processor: ScopeTowerProcessor<C>,
|
||||||
resultCollector: ResultCollector<C>,
|
resultCollector: ResultCollector<C>,
|
||||||
useOrder: Boolean
|
useOrder: Boolean,
|
||||||
|
name: Name
|
||||||
): Collection<C> {
|
): Collection<C> {
|
||||||
fun TowerData.process() = processTowerData(processor, resultCollector, useOrder, this)
|
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
|
// Lazy calculation
|
||||||
var nonLocalLevels: Collection<ScopeTowerLevel>? = null
|
var nonLocalLevels: Collection<ScopeTowerLevel>? = null
|
||||||
val hidesMembersLevel = HidesMembersTowerLevel(this)
|
val hidesMembersLevel = HidesMembersTowerLevel(this)
|
||||||
@@ -123,6 +125,11 @@ class TowerResolver {
|
|||||||
// synthetic property for explicit receiver
|
// synthetic property for explicit receiver
|
||||||
TowerData.TowerLevel(syntheticLevel).process()?.let { return it }
|
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
|
// local non-extensions or extension for explicit receiver
|
||||||
for (localLevel in localLevels) {
|
for (localLevel in localLevels) {
|
||||||
TowerData.TowerLevel(localLevel).process()?.let { return it }
|
TowerData.TowerLevel(localLevel).process()?.let { return it }
|
||||||
@@ -173,6 +180,9 @@ class TowerResolver {
|
|||||||
return resultCollector.getFinalCandidates()
|
return resultCollector.getFinalCandidates()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun ResolutionScope.mayFitForName(name: Name) =
|
||||||
|
!definitelyDoesNotContainName(name) || !definitelyDoesNotContainName(OperatorNameConventions.INVOKE)
|
||||||
|
|
||||||
fun <C : Candidate> runWithEmptyTowerData(
|
fun <C : Candidate> runWithEmptyTowerData(
|
||||||
processor: ScopeTowerProcessor<C>,
|
processor: ScopeTowerProcessor<C>,
|
||||||
resultCollector: ResultCollector<C>,
|
resultCollector: ResultCollector<C>,
|
||||||
@@ -234,7 +244,7 @@ class TowerResolver {
|
|||||||
val firstGroupWithResolved = candidateGroups.firstOrNull {
|
val firstGroupWithResolved = candidateGroups.firstOrNull {
|
||||||
it.any { it.resultingApplicability == ResolutionCandidateApplicability.RESOLVED }
|
it.any { it.resultingApplicability == ResolutionCandidateApplicability.RESOLVED }
|
||||||
} ?: return null
|
} ?: return null
|
||||||
|
|
||||||
return firstGroupWithResolved.filter { it.resultingApplicability == ResolutionCandidateApplicability.RESOLVED }
|
return firstGroupWithResolved.filter { it.resultingApplicability == ResolutionCandidateApplicability.RESOLVED }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,8 +271,8 @@ class TowerResolver {
|
|||||||
|
|
||||||
return moreSuitableGroup.filter { it.resultingApplicability == groupApplicability }
|
return moreSuitableGroup.filter { it.resultingApplicability == groupApplicability }
|
||||||
}
|
}
|
||||||
|
|
||||||
private val Collection<C>.groupApplicability get() =
|
private val Collection<C>.groupApplicability get() =
|
||||||
minBy { it.resultingApplicability }?.resultingApplicability ?: ResolutionCandidateApplicability.HIDDEN
|
minBy { it.resultingApplicability }?.resultingApplicability ?: ResolutionCandidateApplicability.HIDDEN
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user