Fix UI freezes caused by calls with a huge number overloads

While we have an overload resolution algorithm working for O(n^2),
call resolution for the single particular call may work more then just
a second.
Thus, we need to call ProgressManager.checkCanceled() with more granularity

^KT-35135 Fixed
This commit is contained in:
Denis Zharkov
2020-02-14 15:42:07 +03:00
parent 842e2dc02f
commit aac72871e7
9 changed files with 52 additions and 5 deletions
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.resolve.calls.tower.ImplicitScopeTower
import org.jetbrains.kotlin.resolve.calls.tower.TowerResolver
import org.jetbrains.kotlin.resolve.calls.tower.isInapplicable
import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.util.CancellationChecker
class CallableReferenceOverloadConflictResolver(
@@ -39,6 +40,7 @@ class CallableReferenceOverloadConflictResolver(
module: ModuleDescriptor,
specificityComparator: TypeSpecificityComparator,
platformOverloadsSpecificityComparator: PlatformOverloadsSpecificityComparator,
cancellationChecker: CancellationChecker,
statelessCallbacks: KotlinResolutionStatelessCallbacks,
constraintInjector: ConstraintInjector
) : OverloadingConflictResolver<CallableReferenceCandidate>(
@@ -46,6 +48,7 @@ class CallableReferenceOverloadConflictResolver(
module,
specificityComparator,
platformOverloadsSpecificityComparator,
cancellationChecker,
{ it.candidate },
{ statelessCallbacks.createConstraintSystemForOverloadResolution(constraintInjector, builtIns) },
Companion::createFlatSignature,
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.resolve.calls.results.OverloadingConflictResolver
import org.jetbrains.kotlin.resolve.calls.results.PlatformOverloadsSpecificityComparator
import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.util.CancellationChecker
import java.util.*
class NewOverloadingConflictResolver(
@@ -34,6 +35,7 @@ class NewOverloadingConflictResolver(
module: ModuleDescriptor,
specificityComparator: TypeSpecificityComparator,
platformOverloadsSpecificityComparator: PlatformOverloadsSpecificityComparator,
cancellationChecker: CancellationChecker,
statelessCallbacks: KotlinResolutionStatelessCallbacks,
constraintInjector: ConstraintInjector
) : OverloadingConflictResolver<KotlinResolutionCandidate>(
@@ -41,6 +43,7 @@ class NewOverloadingConflictResolver(
module,
specificityComparator,
platformOverloadsSpecificityComparator,
cancellationChecker,
{
// todo investigate
it.resolvedCall.candidateDescriptor
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.checker.requireOrDescribe
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.util.CancellationChecker
import java.util.*
open class OverloadingConflictResolver<C : Any>(
@@ -38,6 +39,7 @@ open class OverloadingConflictResolver<C : Any>(
private val module: ModuleDescriptor,
private val specificityComparator: TypeSpecificityComparator,
private val platformOverloadsSpecificityComparator: PlatformOverloadsSpecificityComparator,
private val cancellationChecker: CancellationChecker,
private val getResultingDescriptor: (C) -> CallableDescriptor,
private val createEmptyConstraintSystem: () -> SimpleConstraintSystem,
private val createFlatSignature: (C) -> FlatSignature<C>,
@@ -78,7 +80,8 @@ open class OverloadingConflictResolver<C : Any>(
val noEquivalentCalls = filterOutEquivalentCalls(fixedCandidates)
val noOverrides = OverridingUtil.filterOverrides(
noEquivalentCalls,
isTypeRefinementEnabled
isTypeRefinementEnabled,
cancellationChecker::check
) { a, b ->
val aDescriptor = a.resultingDescriptor
val bDescriptor = b.resultingDescriptor
@@ -124,6 +127,7 @@ open class OverloadingConflictResolver<C : Any>(
val result = LinkedHashSet<C>()
outerLoop@ for (meD in fromSourcesGoesFirst) {
cancellationChecker.check()
for (otherD in result) {
val me = meD.resultingDescriptor.originalIfTypeRefinementEnabled
val other = otherD.resultingDescriptor.originalIfTypeRefinementEnabled
@@ -209,6 +213,7 @@ open class OverloadingConflictResolver<C : Any>(
}
val bestCandidatesByParameterTypes = conflictingCandidates.filter { candidate ->
cancellationChecker.check()
isMostSpecific(candidate, conflictingCandidates) { call1, call2 ->
isNotLessSpecificCallWithArgumentMapping(call1, call2, discriminateGenerics)
}