Skip to content

Commit dfad872

Browse files
committed
[ConstraintSystem] Attempt to apply fixes in AST walker order
This makes sure that the diagnostics appear in the stable order which is closer to what users would expect e.g. evaluation order, otherwise, because disjunctions are currently attempted based on their size, ordering of error messages produced by applying fixes is completely arbitrary.
1 parent 62eccd5 commit dfad872

File tree

2 files changed

+36
-13
lines changed

2 files changed

+36
-13
lines changed

lib/Sema/CSApply.cpp

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7910,21 +7910,43 @@ Expr *ConstraintSystem::coerceToRValue(Expr *expr) {
79107910
/// Emit the fixes computed as part of the solution, returning true if we were
79117911
/// able to emit an error message, or false if none of the fixits worked out.
79127912
bool ConstraintSystem::applySolutionFixes(Expr *E, const Solution &solution) {
7913-
bool diagnosed = false;
7914-
for (unsigned i = 0, e = solution.Fixes.size(); i != e; ++i)
7915-
diagnosed |= applySolutionFix(E, solution, i);
7913+
llvm::SmallDenseMap<Expr *,
7914+
SmallVector<std::pair<Fix, ConstraintLocator *>, 4>>
7915+
fixesPerExpr;
7916+
7917+
for (const auto &fix : solution.Fixes)
7918+
fixesPerExpr[fix.second->getAnchor()].push_back(fix);
7919+
7920+
auto diagnoseExprFailures = [&](Expr *expr) -> bool {
7921+
auto fixes = fixesPerExpr.find(expr);
7922+
if (fixes == fixesPerExpr.end())
7923+
return false;
79167924

7925+
bool diagnosed = false;
7926+
for (auto &fix : fixes->second)
7927+
diagnosed |= applySolutionFix(expr, solution, fix);
7928+
return diagnosed;
7929+
};
7930+
7931+
bool diagnosed = false;
7932+
E->forEachChildExpr([&](Expr *subExpr) -> Expr * {
7933+
// Diagnose root expression at the end to
7934+
// preserve ordering.
7935+
if (subExpr != E)
7936+
diagnosed |= diagnoseExprFailures(subExpr);
7937+
return subExpr;
7938+
});
7939+
7940+
diagnosed |= diagnoseExprFailures(E);
79177941
return diagnosed;
79187942
}
79197943

7920-
/// \brief Apply the specified Fix # to this solution, producing a fixit hint
7921-
/// diagnostic for it and returning true. If the fixit hint turned out to be
7944+
/// \brief Apply the specified Fix to this solution, producing a fix-it hint
7945+
/// diagnostic for it and returning true. If the fix-it hint turned out to be
79227946
/// bogus, this returns false and doesn't emit anything.
7923-
bool ConstraintSystem::applySolutionFix(Expr *expr,
7924-
const Solution &solution,
7925-
unsigned fixNo) {
7926-
auto &fix = solution.Fixes[fixNo];
7927-
7947+
bool ConstraintSystem::applySolutionFix(
7948+
Expr *expr, const Solution &solution,
7949+
std::pair<Fix, ConstraintLocator *> &fix) {
79287950
// Some fixes need more information from the locator.
79297951
ConstraintLocator *locator = fix.second;
79307952

lib/Sema/ConstraintSystem.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1518,10 +1518,11 @@ class ConstraintSystem {
15181518
/// able to emit an error message, or false if none of the fixits worked out.
15191519
bool applySolutionFixes(Expr *E, const Solution &solution);
15201520

1521-
/// \brief Apply the specified Fix # to this solution, producing a fixit hint
1522-
/// diagnostic for it and returning true. If the fixit hint turned out to be
1521+
/// \brief Apply the specified Fix to this solution, producing a fix-it hint
1522+
/// diagnostic for it and returning true. If the fix-it hint turned out to be
15231523
/// bogus, this returns false and doesn't emit anything.
1524-
bool applySolutionFix(Expr *expr, const Solution &solution, unsigned fixNo);
1524+
bool applySolutionFix(Expr *expr, const Solution &solution,
1525+
std::pair<Fix, ConstraintLocator *> &fix);
15251526

15261527
/// \brief If there is more than one viable solution,
15271528
/// attempt to pick the best solution and remove all of the rest.

0 commit comments

Comments
 (0)