From 3df5667a4b3bf3451e71993ebcee1e5703ea298d Mon Sep 17 00:00:00 2001 From: Victor Petukhov Date: Thu, 19 Aug 2021 08:45:32 +0300 Subject: [PATCH] Split variables fixation and reporting "not enough type infromation" in the type system completer into two parts --- .../KotlinConstraintSystemCompleter.kt | 103 +++++++++--------- 1 file changed, 54 insertions(+), 49 deletions(-) diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/KotlinConstraintSystemCompleter.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/KotlinConstraintSystemCompleter.kt index 38f7370adc3..f2ab0c5f26c 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/KotlinConstraintSystemCompleter.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/KotlinConstraintSystemCompleter.kt @@ -133,8 +133,12 @@ class KotlinConstraintSystemCompleter( if (analyzeNextReadyPostponedArgument(postponedArguments, completionMode, analyze)) continue - // Stage 6: fix type variables – fix if possible or report not enough information (if completion mode is full) - val wasFixedSomeVariable = fixVariablesOrReportNotEnoughInformation( + // Stage 6: fix next ready type variable with proper constraints + if (fixNextReadyVariable(completionMode, topLevelAtoms, topLevelType, collectVariablesFromContext, postponedArguments)) + continue + + // Stage 7: report "not enough information" for uninferred type variables + reportNotEnoughTypeInformation( completionMode, topLevelAtoms, topLevelType, collectVariablesFromContext, postponedArguments, diagnosticsHolder ) if (wasFixedSomeVariable) @@ -271,69 +275,70 @@ class KotlinConstraintSystemCompleter( c.fixVariable(variable, resultType, FixVariableConstraintPositionImpl(variable, resolvedAtom)) } - private fun ConstraintSystemCompletionContext.fixVariablesOrReportNotEnoughInformation( + private fun ConstraintSystemCompletionContext.fixNextReadyVariable( + completionMode: ConstraintSystemCompletionMode, + topLevelAtoms: List, + topLevelType: UnwrappedType, + collectVariablesFromContext: Boolean, + postponedArguments: List, + ): Boolean { + val variableForFixation = variableFixationFinder.findFirstVariableForFixation( + this, getOrderedAllTypeVariables(collectVariablesFromContext, topLevelAtoms), + postponedArguments, completionMode, topLevelType, + ) ?: return false + + if (!variableForFixation.hasProperConstraint) return false + + fixVariable(this, notFixedTypeVariables.getValue(variableForFixation.variable), topLevelAtoms) + + return true + } + + private fun ConstraintSystemCompletionContext.reportNotEnoughTypeInformation( completionMode: ConstraintSystemCompletionMode, topLevelAtoms: List, topLevelType: UnwrappedType, collectVariablesFromContext: Boolean, postponedArguments: List, diagnosticsHolder: KotlinDiagnosticsHolder - ): Boolean { + ) { while (true) { val variableForFixation = variableFixationFinder.findFirstVariableForFixation( - this, - getOrderedAllTypeVariables(collectVariablesFromContext, topLevelAtoms), - postponedArguments, - completionMode, - topLevelType, + this, getOrderedAllTypeVariables(collectVariablesFromContext, topLevelAtoms), + postponedArguments, completionMode, topLevelType, ) ?: break - if (!variableForFixation.hasProperConstraint && completionMode == ConstraintSystemCompletionMode.PARTIAL) - break + assert(!variableForFixation.hasProperConstraint) { + "At this stage there should be no remaining variables with proper constraints" + } + + if (completionMode == ConstraintSystemCompletionMode.PARTIAL) break val variableWithConstraints = notFixedTypeVariables.getValue(variableForFixation.variable) + val typeVariable = variableWithConstraints.typeVariable + val resolvedAtom = findResolvedAtomBy(typeVariable, topLevelAtoms) ?: topLevelAtoms.firstOrNull() - when { - variableForFixation.hasProperConstraint -> { - fixVariable(this, variableWithConstraints, topLevelAtoms) - return true - } - - else -> processVariableWhenNotEnoughInformation(this, variableWithConstraints, topLevelAtoms, diagnosticsHolder) - } - } - - return false - } - - private fun processVariableWhenNotEnoughInformation( - c: ConstraintSystemCompletionContext, - variableWithConstraints: VariableWithConstraints, - topLevelAtoms: List, - diagnosticsHolder: KotlinDiagnosticsHolder - ) { - val typeVariable = variableWithConstraints.typeVariable - val resolvedAtom = findResolvedAtomBy(typeVariable, topLevelAtoms) ?: topLevelAtoms.firstOrNull() - - if (resolvedAtom != null) { - c.addError( - NotEnoughInformationForTypeParameterImpl(typeVariable, resolvedAtom, c.couldBeResolvedWithUnrestrictedBuilderInference()) - ) - } - - val resultErrorType = when { - typeVariable is TypeVariableFromCallableDescriptor -> - ErrorUtils.createUninferredParameterType(typeVariable.originalTypeParameter) - typeVariable is TypeVariableForLambdaParameterType && typeVariable.atom is LambdaKotlinCallArgument -> { - diagnosticsHolder.addDiagnostic( - NotEnoughInformationForLambdaParameter(typeVariable.atom, typeVariable.index) + if (resolvedAtom != null) { + addError( + NotEnoughInformationForTypeParameterImpl(typeVariable, resolvedAtom, couldBeResolvedWithUnrestrictedBuilderInference()) ) - ErrorUtils.createErrorType("Cannot infer lambda parameter type") } - else -> ErrorUtils.createErrorType("Cannot infer type variable $typeVariable") - } - c.fixVariable(typeVariable, resultErrorType, FixVariableConstraintPositionImpl(typeVariable, resolvedAtom)) + val resultErrorType = when { + typeVariable is TypeVariableFromCallableDescriptor -> { + ErrorUtils.createUninferredParameterType(typeVariable.originalTypeParameter) + } + typeVariable is TypeVariableForLambdaParameterType && typeVariable.atom is LambdaKotlinCallArgument -> { + diagnosticsHolder.addDiagnostic( + NotEnoughInformationForLambdaParameter(typeVariable.atom, typeVariable.index) + ) + ErrorUtils.createErrorType("Cannot infer lambda parameter type") + } + else -> ErrorUtils.createErrorType("Cannot infer type variable $typeVariable") + } + + fixVariable(typeVariable, resultErrorType, FixVariableConstraintPositionImpl(typeVariable, resolvedAtom)) + } } private fun ConstraintSystemCompletionContext.getOrderedAllTypeVariables(