Split variables fixation and reporting "not enough type infromation" in the type system completer into two parts
This commit is contained in:
committed by
TeamCityServer
parent
261a04b587
commit
3df5667a4b
+54
-49
@@ -133,8 +133,12 @@ class KotlinConstraintSystemCompleter(
|
|||||||
if (analyzeNextReadyPostponedArgument(postponedArguments, completionMode, analyze))
|
if (analyzeNextReadyPostponedArgument(postponedArguments, completionMode, analyze))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
// Stage 6: fix type variables – fix if possible or report not enough information (if completion mode is full)
|
// Stage 6: fix next ready type variable with proper constraints
|
||||||
val wasFixedSomeVariable = fixVariablesOrReportNotEnoughInformation(
|
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
|
completionMode, topLevelAtoms, topLevelType, collectVariablesFromContext, postponedArguments, diagnosticsHolder
|
||||||
)
|
)
|
||||||
if (wasFixedSomeVariable)
|
if (wasFixedSomeVariable)
|
||||||
@@ -271,69 +275,70 @@ class KotlinConstraintSystemCompleter(
|
|||||||
c.fixVariable(variable, resultType, FixVariableConstraintPositionImpl(variable, resolvedAtom))
|
c.fixVariable(variable, resultType, FixVariableConstraintPositionImpl(variable, resolvedAtom))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ConstraintSystemCompletionContext.fixVariablesOrReportNotEnoughInformation(
|
private fun ConstraintSystemCompletionContext.fixNextReadyVariable(
|
||||||
|
completionMode: ConstraintSystemCompletionMode,
|
||||||
|
topLevelAtoms: List<ResolvedAtom>,
|
||||||
|
topLevelType: UnwrappedType,
|
||||||
|
collectVariablesFromContext: Boolean,
|
||||||
|
postponedArguments: List<PostponedResolvedAtom>,
|
||||||
|
): 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,
|
completionMode: ConstraintSystemCompletionMode,
|
||||||
topLevelAtoms: List<ResolvedAtom>,
|
topLevelAtoms: List<ResolvedAtom>,
|
||||||
topLevelType: UnwrappedType,
|
topLevelType: UnwrappedType,
|
||||||
collectVariablesFromContext: Boolean,
|
collectVariablesFromContext: Boolean,
|
||||||
postponedArguments: List<PostponedResolvedAtom>,
|
postponedArguments: List<PostponedResolvedAtom>,
|
||||||
diagnosticsHolder: KotlinDiagnosticsHolder
|
diagnosticsHolder: KotlinDiagnosticsHolder
|
||||||
): Boolean {
|
) {
|
||||||
while (true) {
|
while (true) {
|
||||||
val variableForFixation = variableFixationFinder.findFirstVariableForFixation(
|
val variableForFixation = variableFixationFinder.findFirstVariableForFixation(
|
||||||
this,
|
this, getOrderedAllTypeVariables(collectVariablesFromContext, topLevelAtoms),
|
||||||
getOrderedAllTypeVariables(collectVariablesFromContext, topLevelAtoms),
|
postponedArguments, completionMode, topLevelType,
|
||||||
postponedArguments,
|
|
||||||
completionMode,
|
|
||||||
topLevelType,
|
|
||||||
) ?: break
|
) ?: break
|
||||||
|
|
||||||
if (!variableForFixation.hasProperConstraint && completionMode == ConstraintSystemCompletionMode.PARTIAL)
|
assert(!variableForFixation.hasProperConstraint) {
|
||||||
break
|
"At this stage there should be no remaining variables with proper constraints"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (completionMode == ConstraintSystemCompletionMode.PARTIAL) break
|
||||||
|
|
||||||
val variableWithConstraints = notFixedTypeVariables.getValue(variableForFixation.variable)
|
val variableWithConstraints = notFixedTypeVariables.getValue(variableForFixation.variable)
|
||||||
|
val typeVariable = variableWithConstraints.typeVariable
|
||||||
|
val resolvedAtom = findResolvedAtomBy(typeVariable, topLevelAtoms) ?: topLevelAtoms.firstOrNull()
|
||||||
|
|
||||||
when {
|
if (resolvedAtom != null) {
|
||||||
variableForFixation.hasProperConstraint -> {
|
addError(
|
||||||
fixVariable(this, variableWithConstraints, topLevelAtoms)
|
NotEnoughInformationForTypeParameterImpl(typeVariable, resolvedAtom, couldBeResolvedWithUnrestrictedBuilderInference())
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> processVariableWhenNotEnoughInformation(this, variableWithConstraints, topLevelAtoms, diagnosticsHolder)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun processVariableWhenNotEnoughInformation(
|
|
||||||
c: ConstraintSystemCompletionContext,
|
|
||||||
variableWithConstraints: VariableWithConstraints,
|
|
||||||
topLevelAtoms: List<ResolvedAtom>,
|
|
||||||
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)
|
|
||||||
)
|
)
|
||||||
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(
|
private fun ConstraintSystemCompletionContext.getOrderedAllTypeVariables(
|
||||||
|
|||||||
Reference in New Issue
Block a user