[NI] Extend constraint completer to work with several resolve atoms

This commit is contained in:
Mikhail Zarechenskiy
2018-03-14 14:37:57 +03:00
parent a47a916437
commit 887a69b72e
2 changed files with 30 additions and 31 deletions
@@ -96,7 +96,7 @@ class KotlinCallCompleter(
kotlinConstraintSystemCompleter.runCompletion( kotlinConstraintSystemCompleter.runCompletion(
constraintSystem.asConstraintSystemCompleterContext(), constraintSystem.asConstraintSystemCompleterContext(),
completionMode, completionMode,
resolvedCallAtom, listOf(resolvedCallAtom),
returnType returnType
) { ) {
if (collectAllCandidatesMode) { if (collectAllCandidatesMode) {
@@ -1,17 +1,6 @@
/* /*
* Copyright 2010-2017 JetBrains s.r.o. * Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* * that can be found in the license/LICENSE.txt file.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ */
package org.jetbrains.kotlin.resolve.calls.inference.components package org.jetbrains.kotlin.resolve.calls.inference.components
@@ -50,22 +39,22 @@ class KotlinConstraintSystemCompleter(
fun runCompletion( fun runCompletion(
c: Context, c: Context,
completionMode: ConstraintSystemCompletionMode, completionMode: ConstraintSystemCompletionMode,
topLevelPrimitive: ResolvedAtom, topLevelAtoms: List<ResolvedAtom>,
topLevelType: UnwrappedType, topLevelType: UnwrappedType,
analyze: (PostponedResolvedAtom) -> Unit analyze: (PostponedResolvedAtom) -> Unit
) { ) {
while (true) { while (true) {
if (analyzePostponeArgumentIfPossible(c, topLevelPrimitive, analyze)) continue if (analyzePostponeArgumentIfPossible(c, topLevelAtoms, analyze)) continue
val allTypeVariables = getOrderedAllTypeVariables(c, topLevelPrimitive) val allTypeVariables = getOrderedAllTypeVariables(c, topLevelAtoms)
val postponedKtPrimitives = getOrderedNotAnalyzedPostponedArguments(topLevelPrimitive) val postponedKtPrimitives = getOrderedNotAnalyzedPostponedArguments(topLevelAtoms)
val variableForFixation = variableFixationFinder.findFirstVariableForFixation( val variableForFixation = variableFixationFinder.findFirstVariableForFixation(
c, allTypeVariables, postponedKtPrimitives, completionMode, topLevelType c, allTypeVariables, postponedKtPrimitives, completionMode, topLevelType
) )
if (shouldForceCallableReferenceOrLambdaResolution(completionMode, variableForFixation)) { if (shouldForceCallableReferenceOrLambdaResolution(completionMode, variableForFixation)) {
if (forcePostponedAtomResolution<ResolvedCallableReferenceAtom>(topLevelPrimitive, analyze)) continue if (forcePostponedAtomResolution<ResolvedCallableReferenceAtom>(topLevelAtoms, analyze)) continue
if (forcePostponedAtomResolution<LambdaWithTypeVariableAsExpectedTypeAtom>(topLevelPrimitive, analyze)) continue if (forcePostponedAtomResolution<LambdaWithTypeVariableAsExpectedTypeAtom>(topLevelAtoms, analyze)) continue
} }
if (variableForFixation != null) { if (variableForFixation != null) {
@@ -85,7 +74,7 @@ class KotlinConstraintSystemCompleter(
if (completionMode == ConstraintSystemCompletionMode.FULL) { if (completionMode == ConstraintSystemCompletionMode.FULL) {
// force resolution for all not-analyzed argument's // force resolution for all not-analyzed argument's
getOrderedNotAnalyzedPostponedArguments(topLevelPrimitive).forEach(analyze) getOrderedNotAnalyzedPostponedArguments(topLevelAtoms).forEach(analyze)
} }
} }
@@ -102,10 +91,10 @@ class KotlinConstraintSystemCompleter(
// true if we do analyze // true if we do analyze
private fun analyzePostponeArgumentIfPossible( private fun analyzePostponeArgumentIfPossible(
c: Context, c: Context,
topLevelPrimitive: ResolvedAtom, topLevelAtoms: List<ResolvedAtom>,
analyze: (PostponedResolvedAtom) -> Unit analyze: (PostponedResolvedAtom) -> Unit
): Boolean { ): Boolean {
for (argument in getOrderedNotAnalyzedPostponedArguments(topLevelPrimitive)) { for (argument in getOrderedNotAnalyzedPostponedArguments(topLevelAtoms)) {
if (canWeAnalyzeIt(c, argument)) { if (canWeAnalyzeIt(c, argument)) {
analyze(argument) analyze(argument)
return true return true
@@ -116,15 +105,15 @@ class KotlinConstraintSystemCompleter(
// true if we find some callable reference and run resolution for it. Note that such resolution can be unsuccessful // true if we find some callable reference and run resolution for it. Note that such resolution can be unsuccessful
private inline fun <reified T : PostponedResolvedAtom> forcePostponedAtomResolution( private inline fun <reified T : PostponedResolvedAtom> forcePostponedAtomResolution(
topLevelPrimitive: ResolvedAtom, topLevelAtoms: List<ResolvedAtom>,
analyze: (PostponedResolvedAtom) -> Unit analyze: (PostponedResolvedAtom) -> Unit
): Boolean { ): Boolean {
val postponedArgument = getOrderedNotAnalyzedPostponedArguments(topLevelPrimitive).firstIsInstanceOrNull<T>() ?: return false val postponedArgument = getOrderedNotAnalyzedPostponedArguments(topLevelAtoms).firstIsInstanceOrNull<T>() ?: return false
analyze(postponedArgument) analyze(postponedArgument)
return true return true
} }
private fun getOrderedNotAnalyzedPostponedArguments(topLevelPrimitive: ResolvedAtom): List<PostponedResolvedAtom> { private fun getOrderedNotAnalyzedPostponedArguments(topLevelAtoms: List<ResolvedAtom>): List<PostponedResolvedAtom> {
fun ResolvedAtom.process(to: MutableList<PostponedResolvedAtom>) { fun ResolvedAtom.process(to: MutableList<PostponedResolvedAtom>) {
to.addIfNotNull(this.safeAs<PostponedResolvedAtom>()?.takeUnless { it.analyzed }) to.addIfNotNull(this.safeAs<PostponedResolvedAtom>()?.takeUnless { it.analyzed })
@@ -132,11 +121,17 @@ class KotlinConstraintSystemCompleter(
subResolvedAtoms.forEach { it.process(to) } subResolvedAtoms.forEach { it.process(to) }
} }
} }
return arrayListOf<PostponedResolvedAtom>().apply { topLevelPrimitive.process(this) }
val notAnalyzedArguments = arrayListOf<PostponedResolvedAtom>()
for (primitive in topLevelAtoms) {
primitive.process(notAnalyzedArguments)
}
return notAnalyzedArguments
} }
private fun getOrderedAllTypeVariables(c: Context, topLevelPrimitive: ResolvedAtom): List<TypeConstructor> { private fun getOrderedAllTypeVariables(c: Context, topLevelAtoms: List<ResolvedAtom>): List<TypeConstructor> {
fun ResolvedAtom.process(to: MutableList<TypeConstructor>) { fun ResolvedAtom.process(to: LinkedHashSet<TypeConstructor>) {
val typeVariables = when (this) { val typeVariables = when (this) {
is ResolvedCallAtom -> substitutor.freshVariables is ResolvedCallAtom -> substitutor.freshVariables
is ResolvedCallableReferenceAtom -> candidate?.freshSubstitutor?.freshVariables.orEmpty() is ResolvedCallableReferenceAtom -> candidate?.freshSubstitutor?.freshVariables.orEmpty()
@@ -153,14 +148,18 @@ class KotlinConstraintSystemCompleter(
} }
} }
val result = arrayListOf<TypeConstructor>().apply { topLevelPrimitive.process(this) } // Note that it's important to use Set here, because several atoms can share the same type variable
val result = linkedSetOf<TypeConstructor>()
for (primitive in topLevelAtoms) {
primitive.process(result)
}
assert(result.size == c.notFixedTypeVariables.size) { assert(result.size == c.notFixedTypeVariables.size) {
val notFoundTypeVariables = c.notFixedTypeVariables.keys.toMutableSet().removeAll(result) val notFoundTypeVariables = c.notFixedTypeVariables.keys.toMutableSet().removeAll(result)
"Not all type variables found: $notFoundTypeVariables" "Not all type variables found: $notFoundTypeVariables"
} }
return result return result.toList()
} }