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:
@@ -41,6 +41,7 @@ import org.jetbrains.kotlin.types.checker.NewKotlinTypeCheckerImpl
|
|||||||
import org.jetbrains.kotlin.types.expressions.DeclarationScopeProviderForLocalClassifierAnalyzer
|
import org.jetbrains.kotlin.types.expressions.DeclarationScopeProviderForLocalClassifierAnalyzer
|
||||||
import org.jetbrains.kotlin.types.expressions.LocalClassDescriptorHolder
|
import org.jetbrains.kotlin.types.expressions.LocalClassDescriptorHolder
|
||||||
import org.jetbrains.kotlin.types.expressions.LocalLazyDeclarationResolver
|
import org.jetbrains.kotlin.types.expressions.LocalLazyDeclarationResolver
|
||||||
|
import org.jetbrains.kotlin.util.ProgressManagerBasedCancellationChecker
|
||||||
|
|
||||||
fun StorageComponentContainer.configureModule(
|
fun StorageComponentContainer.configureModule(
|
||||||
moduleContext: ModuleContext,
|
moduleContext: ModuleContext,
|
||||||
@@ -97,6 +98,7 @@ private fun StorageComponentContainer.configurePlatformIndependentComponents() {
|
|||||||
useImpl<CompilerDeserializationConfiguration>()
|
useImpl<CompilerDeserializationConfiguration>()
|
||||||
|
|
||||||
useImpl<ClassicTypeSystemContextForCS>()
|
useImpl<ClassicTypeSystemContextForCS>()
|
||||||
|
useInstance(ProgressManagerBasedCancellationChecker)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+4
-1
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
|||||||
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCallImpl
|
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCallImpl
|
||||||
import org.jetbrains.kotlin.resolve.calls.results.FlatSignature.Companion.argumentValueType
|
import org.jetbrains.kotlin.resolve.calls.results.FlatSignature.Companion.argumentValueType
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.util.CancellationChecker
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
@@ -55,12 +56,14 @@ fun createOverloadingConflictResolver(
|
|||||||
builtIns: KotlinBuiltIns,
|
builtIns: KotlinBuiltIns,
|
||||||
module: ModuleDescriptor,
|
module: ModuleDescriptor,
|
||||||
specificityComparator: TypeSpecificityComparator,
|
specificityComparator: TypeSpecificityComparator,
|
||||||
platformOverloadsSpecificityComparator: PlatformOverloadsSpecificityComparator
|
platformOverloadsSpecificityComparator: PlatformOverloadsSpecificityComparator,
|
||||||
|
cancellationChecker: CancellationChecker,
|
||||||
) = OverloadingConflictResolver(
|
) = OverloadingConflictResolver(
|
||||||
builtIns,
|
builtIns,
|
||||||
module,
|
module,
|
||||||
specificityComparator,
|
specificityComparator,
|
||||||
platformOverloadsSpecificityComparator,
|
platformOverloadsSpecificityComparator,
|
||||||
|
cancellationChecker,
|
||||||
MutableResolvedCall<*>::getResultingDescriptor,
|
MutableResolvedCall<*>::getResultingDescriptor,
|
||||||
ConstraintSystemBuilderImpl.Companion::forSpecificity,
|
ConstraintSystemBuilderImpl.Companion::forSpecificity,
|
||||||
MutableResolvedCall<*>::createFlatSignature,
|
MutableResolvedCall<*>::createFlatSignature,
|
||||||
|
|||||||
+4
-2
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode;
|
|||||||
import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall;
|
import org.jetbrains.kotlin.resolve.calls.model.MutableResolvedCall;
|
||||||
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy;
|
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy;
|
||||||
import org.jetbrains.kotlin.resolve.calls.tower.TowerUtilsKt;
|
import org.jetbrains.kotlin.resolve.calls.tower.TowerUtilsKt;
|
||||||
|
import org.jetbrains.kotlin.util.CancellationChecker;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@@ -42,10 +43,11 @@ public class ResolutionResultsHandler {
|
|||||||
@NotNull KotlinBuiltIns builtIns,
|
@NotNull KotlinBuiltIns builtIns,
|
||||||
@NotNull ModuleDescriptor module,
|
@NotNull ModuleDescriptor module,
|
||||||
@NotNull TypeSpecificityComparator specificityComparator,
|
@NotNull TypeSpecificityComparator specificityComparator,
|
||||||
@NotNull PlatformOverloadsSpecificityComparator platformOverloadsSpecificityComparator
|
@NotNull PlatformOverloadsSpecificityComparator platformOverloadsSpecificityComparator,
|
||||||
|
@NotNull CancellationChecker cancellationChecker
|
||||||
) {
|
) {
|
||||||
overloadingConflictResolver = FlatSignatureForResolvedCallKt.createOverloadingConflictResolver(
|
overloadingConflictResolver = FlatSignatureForResolvedCallKt.createOverloadingConflictResolver(
|
||||||
builtIns, module, specificityComparator, platformOverloadsSpecificityComparator
|
builtIns, module, specificityComparator, platformOverloadsSpecificityComparator, cancellationChecker
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.util
|
||||||
|
|
||||||
|
import com.intellij.openapi.progress.ProgressManager
|
||||||
|
|
||||||
|
object ProgressManagerBasedCancellationChecker : CancellationChecker {
|
||||||
|
override fun check() {
|
||||||
|
ProgressManager.checkCanceled()
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
@@ -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.TowerResolver
|
||||||
import org.jetbrains.kotlin.resolve.calls.tower.isInapplicable
|
import org.jetbrains.kotlin.resolve.calls.tower.isInapplicable
|
||||||
import org.jetbrains.kotlin.types.UnwrappedType
|
import org.jetbrains.kotlin.types.UnwrappedType
|
||||||
|
import org.jetbrains.kotlin.util.CancellationChecker
|
||||||
|
|
||||||
|
|
||||||
class CallableReferenceOverloadConflictResolver(
|
class CallableReferenceOverloadConflictResolver(
|
||||||
@@ -39,6 +40,7 @@ class CallableReferenceOverloadConflictResolver(
|
|||||||
module: ModuleDescriptor,
|
module: ModuleDescriptor,
|
||||||
specificityComparator: TypeSpecificityComparator,
|
specificityComparator: TypeSpecificityComparator,
|
||||||
platformOverloadsSpecificityComparator: PlatformOverloadsSpecificityComparator,
|
platformOverloadsSpecificityComparator: PlatformOverloadsSpecificityComparator,
|
||||||
|
cancellationChecker: CancellationChecker,
|
||||||
statelessCallbacks: KotlinResolutionStatelessCallbacks,
|
statelessCallbacks: KotlinResolutionStatelessCallbacks,
|
||||||
constraintInjector: ConstraintInjector
|
constraintInjector: ConstraintInjector
|
||||||
) : OverloadingConflictResolver<CallableReferenceCandidate>(
|
) : OverloadingConflictResolver<CallableReferenceCandidate>(
|
||||||
@@ -46,6 +48,7 @@ class CallableReferenceOverloadConflictResolver(
|
|||||||
module,
|
module,
|
||||||
specificityComparator,
|
specificityComparator,
|
||||||
platformOverloadsSpecificityComparator,
|
platformOverloadsSpecificityComparator,
|
||||||
|
cancellationChecker,
|
||||||
{ it.candidate },
|
{ it.candidate },
|
||||||
{ statelessCallbacks.createConstraintSystemForOverloadResolution(constraintInjector, builtIns) },
|
{ statelessCallbacks.createConstraintSystemForOverloadResolution(constraintInjector, builtIns) },
|
||||||
Companion::createFlatSignature,
|
Companion::createFlatSignature,
|
||||||
|
|||||||
+3
@@ -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.PlatformOverloadsSpecificityComparator
|
||||||
import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
|
import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.util.CancellationChecker
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class NewOverloadingConflictResolver(
|
class NewOverloadingConflictResolver(
|
||||||
@@ -34,6 +35,7 @@ class NewOverloadingConflictResolver(
|
|||||||
module: ModuleDescriptor,
|
module: ModuleDescriptor,
|
||||||
specificityComparator: TypeSpecificityComparator,
|
specificityComparator: TypeSpecificityComparator,
|
||||||
platformOverloadsSpecificityComparator: PlatformOverloadsSpecificityComparator,
|
platformOverloadsSpecificityComparator: PlatformOverloadsSpecificityComparator,
|
||||||
|
cancellationChecker: CancellationChecker,
|
||||||
statelessCallbacks: KotlinResolutionStatelessCallbacks,
|
statelessCallbacks: KotlinResolutionStatelessCallbacks,
|
||||||
constraintInjector: ConstraintInjector
|
constraintInjector: ConstraintInjector
|
||||||
) : OverloadingConflictResolver<KotlinResolutionCandidate>(
|
) : OverloadingConflictResolver<KotlinResolutionCandidate>(
|
||||||
@@ -41,6 +43,7 @@ class NewOverloadingConflictResolver(
|
|||||||
module,
|
module,
|
||||||
specificityComparator,
|
specificityComparator,
|
||||||
platformOverloadsSpecificityComparator,
|
platformOverloadsSpecificityComparator,
|
||||||
|
cancellationChecker,
|
||||||
{
|
{
|
||||||
// todo investigate
|
// todo investigate
|
||||||
it.resolvedCall.candidateDescriptor
|
it.resolvedCall.candidateDescriptor
|
||||||
|
|||||||
+6
-1
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.types.KotlinType
|
|||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
import org.jetbrains.kotlin.types.checker.requireOrDescribe
|
import org.jetbrains.kotlin.types.checker.requireOrDescribe
|
||||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||||
|
import org.jetbrains.kotlin.util.CancellationChecker
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
open class OverloadingConflictResolver<C : Any>(
|
open class OverloadingConflictResolver<C : Any>(
|
||||||
@@ -38,6 +39,7 @@ open class OverloadingConflictResolver<C : Any>(
|
|||||||
private val module: ModuleDescriptor,
|
private val module: ModuleDescriptor,
|
||||||
private val specificityComparator: TypeSpecificityComparator,
|
private val specificityComparator: TypeSpecificityComparator,
|
||||||
private val platformOverloadsSpecificityComparator: PlatformOverloadsSpecificityComparator,
|
private val platformOverloadsSpecificityComparator: PlatformOverloadsSpecificityComparator,
|
||||||
|
private val cancellationChecker: CancellationChecker,
|
||||||
private val getResultingDescriptor: (C) -> CallableDescriptor,
|
private val getResultingDescriptor: (C) -> CallableDescriptor,
|
||||||
private val createEmptyConstraintSystem: () -> SimpleConstraintSystem,
|
private val createEmptyConstraintSystem: () -> SimpleConstraintSystem,
|
||||||
private val createFlatSignature: (C) -> FlatSignature<C>,
|
private val createFlatSignature: (C) -> FlatSignature<C>,
|
||||||
@@ -78,7 +80,8 @@ open class OverloadingConflictResolver<C : Any>(
|
|||||||
val noEquivalentCalls = filterOutEquivalentCalls(fixedCandidates)
|
val noEquivalentCalls = filterOutEquivalentCalls(fixedCandidates)
|
||||||
val noOverrides = OverridingUtil.filterOverrides(
|
val noOverrides = OverridingUtil.filterOverrides(
|
||||||
noEquivalentCalls,
|
noEquivalentCalls,
|
||||||
isTypeRefinementEnabled
|
isTypeRefinementEnabled,
|
||||||
|
cancellationChecker::check
|
||||||
) { a, b ->
|
) { a, b ->
|
||||||
val aDescriptor = a.resultingDescriptor
|
val aDescriptor = a.resultingDescriptor
|
||||||
val bDescriptor = b.resultingDescriptor
|
val bDescriptor = b.resultingDescriptor
|
||||||
@@ -124,6 +127,7 @@ open class OverloadingConflictResolver<C : Any>(
|
|||||||
|
|
||||||
val result = LinkedHashSet<C>()
|
val result = LinkedHashSet<C>()
|
||||||
outerLoop@ for (meD in fromSourcesGoesFirst) {
|
outerLoop@ for (meD in fromSourcesGoesFirst) {
|
||||||
|
cancellationChecker.check()
|
||||||
for (otherD in result) {
|
for (otherD in result) {
|
||||||
val me = meD.resultingDescriptor.originalIfTypeRefinementEnabled
|
val me = meD.resultingDescriptor.originalIfTypeRefinementEnabled
|
||||||
val other = otherD.resultingDescriptor.originalIfTypeRefinementEnabled
|
val other = otherD.resultingDescriptor.originalIfTypeRefinementEnabled
|
||||||
@@ -209,6 +213,7 @@ open class OverloadingConflictResolver<C : Any>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val bestCandidatesByParameterTypes = conflictingCandidates.filter { candidate ->
|
val bestCandidatesByParameterTypes = conflictingCandidates.filter { candidate ->
|
||||||
|
cancellationChecker.check()
|
||||||
isMostSpecific(candidate, conflictingCandidates) { call1, call2 ->
|
isMostSpecific(candidate, conflictingCandidates) { call1, call2 ->
|
||||||
isNotLessSpecificCallWithArgumentMapping(call1, call2, discriminateGenerics)
|
isNotLessSpecificCallWithArgumentMapping(call1, call2, discriminateGenerics)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import kotlin.Pair;
|
|||||||
import kotlin.Unit;
|
import kotlin.Unit;
|
||||||
import kotlin.annotations.jvm.Mutable;
|
import kotlin.annotations.jvm.Mutable;
|
||||||
import kotlin.collections.CollectionsKt;
|
import kotlin.collections.CollectionsKt;
|
||||||
|
import kotlin.jvm.functions.Function0;
|
||||||
import kotlin.jvm.functions.Function1;
|
import kotlin.jvm.functions.Function1;
|
||||||
import kotlin.jvm.functions.Function2;
|
import kotlin.jvm.functions.Function2;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -97,7 +98,7 @@ public class OverridingUtil {
|
|||||||
DescriptorUtilsKt
|
DescriptorUtilsKt
|
||||||
.isTypeRefinementEnabled(DescriptorUtilsKt.getModule(candidateSet.iterator().next()));
|
.isTypeRefinementEnabled(DescriptorUtilsKt.getModule(candidateSet.iterator().next()));
|
||||||
|
|
||||||
return filterOverrides(candidateSet, allowDescriptorCopies, new Function2<D, D, Pair<CallableDescriptor, CallableDescriptor>>() {
|
return filterOverrides(candidateSet, allowDescriptorCopies, null, new Function2<D, D, Pair<CallableDescriptor, CallableDescriptor>>() {
|
||||||
@Override
|
@Override
|
||||||
public Pair<CallableDescriptor, CallableDescriptor> invoke(D a, D b) {
|
public Pair<CallableDescriptor, CallableDescriptor> invoke(D a, D b) {
|
||||||
return new Pair<CallableDescriptor, CallableDescriptor>(a, b);
|
return new Pair<CallableDescriptor, CallableDescriptor>(a, b);
|
||||||
@@ -109,6 +110,7 @@ public class OverridingUtil {
|
|||||||
public static <D> Set<D> filterOverrides(
|
public static <D> Set<D> filterOverrides(
|
||||||
@NotNull Set<D> candidateSet,
|
@NotNull Set<D> candidateSet,
|
||||||
boolean allowDescriptorCopies,
|
boolean allowDescriptorCopies,
|
||||||
|
@Nullable Function0<?> cancellationCallback,
|
||||||
@NotNull Function2<? super D, ? super D, Pair<CallableDescriptor, CallableDescriptor>> transformFirst
|
@NotNull Function2<? super D, ? super D, Pair<CallableDescriptor, CallableDescriptor>> transformFirst
|
||||||
) {
|
) {
|
||||||
if (candidateSet.size() <= 1) return candidateSet;
|
if (candidateSet.size() <= 1) return candidateSet;
|
||||||
@@ -116,6 +118,9 @@ public class OverridingUtil {
|
|||||||
Set<D> result = new LinkedHashSet<D>();
|
Set<D> result = new LinkedHashSet<D>();
|
||||||
outerLoop:
|
outerLoop:
|
||||||
for (D meD : candidateSet) {
|
for (D meD : candidateSet) {
|
||||||
|
if (cancellationCallback != null) {
|
||||||
|
cancellationCallback.invoke();
|
||||||
|
}
|
||||||
for (Iterator<D> iterator = result.iterator(); iterator.hasNext(); ) {
|
for (Iterator<D> iterator = result.iterator(); iterator.hasNext(); ) {
|
||||||
D otherD = iterator.next();
|
D otherD = iterator.next();
|
||||||
Pair<CallableDescriptor, CallableDescriptor> meAndOther = transformFirst.invoke(meD, otherD);
|
Pair<CallableDescriptor, CallableDescriptor> meAndOther = transformFirst.invoke(meD, otherD);
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.util
|
||||||
|
|
||||||
|
interface CancellationChecker {
|
||||||
|
fun check()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user