Skip to content

Commit 2384eb2

Browse files
committed
[CSStep] Conjunction: Stop after first ambiguous or fixed element
Stop a conjunction after the first invalid element in diagnostic mode. No need to run the inference for other elements once the problem has been found. All ambiguities and solutions with fixes are propagated back to the outer context to be diagnosed.
1 parent 2ee5b30 commit 2384eb2

File tree

1 file changed

+48
-3
lines changed

1 file changed

+48
-3
lines changed

lib/Sema/CSStep.cpp

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -849,11 +849,29 @@ StepResult ConjunctionStep::resume(bool prevFailed) {
849849

850850
// There could be a local ambiguity related to
851851
// the current element, let's try to resolve it.
852-
if (Solutions.size() > 1) {
852+
if (Solutions.size() > 1)
853853
filterSolutions(Solutions, /*minimize=*/true);
854854

855-
if (Solutions.size() != 1)
856-
return failConjunction();
855+
// In diagnostic mode we need to stop a conjunction
856+
// but consider it successful if there are:
857+
//
858+
// - More than one solution for this element. Ambiguity
859+
// needs to get propagated back to the outer context
860+
// to be diagnosed.
861+
// - A single solution that requires one or more fixes,
862+
// continuing would result in more errors associated
863+
// with the failed element.
864+
if (CS.shouldAttemptFixes()) {
865+
if (Solutions.size() > 1)
866+
Producer.markExhausted();
867+
868+
if (Solutions.size() == 1) {
869+
auto score = Solutions.front().getFixedScore();
870+
if (score.Data[SK_Fix] > 0)
871+
Producer.markExhausted();
872+
}
873+
} else if (Solutions.size() != 1) {
874+
return failConjunction();
857875
}
858876

859877
// Since there is only one solution, let's
@@ -889,6 +907,33 @@ StepResult ConjunctionStep::resume(bool prevFailed) {
889907
Snapshot &&
890908
"Isolated conjunction requires a snapshot of the constraint system");
891909

910+
// In diagnostic mode it's valid for an element to have
911+
// multiple solutions. Ambiguity just needs to be merged
912+
// into the outer context to be property diagnosed.
913+
if (Solutions.size() > 1) {
914+
assert(CS.shouldAttemptFixes());
915+
916+
// Restore all outer type variables, constraints
917+
// and scoring information.
918+
Snapshot.reset();
919+
restoreOuterState();
920+
921+
// Apply all of the information deduced from the
922+
// conjunction (up to the point of ambiguity)
923+
// back to the outer context and form a joined solution.
924+
for (auto &solution : Solutions) {
925+
ConstraintSystem::SolverScope scope(CS);
926+
927+
CS.applySolution(solution);
928+
// Note that `worseThanBestSolution` isn't checked
929+
// here because `Solutions` were pre-filtered, and
930+
// outer score is the same for all of them.
931+
OuterSolutions.push_back(CS.finalize());
932+
}
933+
934+
return done(/*isSuccess=*/true);
935+
}
936+
892937
// Restore outer type variables and prepare to solve
893938
// constraints associated with outer context together
894939
// with information deduced from the conjunction.

0 commit comments

Comments
 (0)