@@ -7458,44 +7458,78 @@ Expr *ConstraintSystem::coerceToRValue(Expr *expr) {
7458
7458
// / Emit the fixes computed as part of the solution, returning true if we were
7459
7459
// / able to emit an error message, or false if none of the fixits worked out.
7460
7460
bool ConstraintSystem::applySolutionFixes (Expr *E, const Solution &solution) {
7461
- llvm::SmallDenseMap<Expr *, SmallVector<const ConstraintFix *, 4 >>
7462
- fixesPerExpr;
7463
-
7461
+ // First transfer all of the deduced information back
7462
+ // to the constraint system.
7464
7463
applySolution (solution);
7465
7464
7466
- for (auto *fix : solution.Fixes )
7467
- fixesPerExpr[fix->getAnchor ()].push_back (fix);
7465
+ class DiagnosticWalker : public ASTWalker {
7466
+ Expr *root;
7467
+ const Solution &solution;
7468
+ llvm::SmallDenseMap<Expr *, SmallVector<ConstraintFix *, 4 >> fixesPerExpr;
7468
7469
7469
- auto diagnoseExprFailures = [&](Expr *expr) -> bool {
7470
- auto fixes = fixesPerExpr.find (expr);
7471
- if (fixes == fixesPerExpr.end ())
7472
- return false ;
7470
+ // / Determines whether any error have been diagnosed while
7471
+ // / trying to apply fixes associated with a given solution.
7472
+ bool DiagnosedAnyErrors = false ;
7473
+
7474
+ public:
7475
+ DiagnosticWalker (Expr *expr, const Solution &solution)
7476
+ : root(expr), solution(solution) {
7477
+ for (auto *fix : solution.Fixes )
7478
+ fixesPerExpr[fix->getAnchor ()].push_back (fix);
7479
+ }
7480
+
7481
+ std::pair<bool , Expr *> walkToExprPre (Expr *E) override {
7482
+ // Diagnose root expression last.
7483
+ if (E == root)
7484
+ return {true , E};
7485
+
7486
+ if (auto *closure = dyn_cast<ClosureExpr>(E)) {
7487
+ auto result = solution.builderTransformedClosures .find (closure);
7488
+ if (result != solution.builderTransformedClosures .end ()) {
7489
+ auto *transformedExpr = result->second .second ;
7490
+ // Since this closure has been transformed into something
7491
+ // else let's look inside transformed expression instead.
7492
+ return {true , transformedExpr};
7493
+ }
7494
+ }
7473
7495
7474
- bool diagnosedError = false ;
7475
- for ( const auto *fix : fixes-> second ) {
7476
- auto diagnosed = fix-> diagnose (E);
7496
+ diagnose (E) ;
7497
+ return { true , E};
7498
+ }
7477
7499
7478
- if (fix->isWarning ()) {
7479
- assert (diagnosed && " warnings should always be diagnosed" );
7480
- (void )diagnosed;
7481
- } else {
7482
- diagnosedError |= diagnosed;
7500
+ Expr *walkToExprPost (Expr *E) override {
7501
+ if (E == root)
7502
+ diagnose (E);
7503
+ return E;
7504
+ }
7505
+
7506
+ std::pair<bool , Stmt *> walkToStmtPre (Stmt *S) override {
7507
+ return {true , S};
7508
+ }
7509
+
7510
+ bool hadErrors () const { return DiagnosedAnyErrors; }
7511
+
7512
+ private:
7513
+ void diagnose (Expr *E) {
7514
+ auto fixes = fixesPerExpr.find (E);
7515
+ if (fixes == fixesPerExpr.end ())
7516
+ return ;
7517
+
7518
+ for (const auto *fix : fixes->second ) {
7519
+ auto diagnosed = fix->diagnose (root);
7520
+ if (fix->isWarning ()) {
7521
+ assert (diagnosed && " warnings should always be diagnosed" );
7522
+ (void )diagnosed;
7523
+ } else {
7524
+ DiagnosedAnyErrors |= diagnosed;
7525
+ }
7483
7526
}
7484
7527
}
7485
- return diagnosedError;
7486
7528
};
7487
7529
7488
- bool diagnosedError = false ;
7489
- E->forEachChildExpr ([&](Expr *subExpr) -> Expr * {
7490
- // Diagnose root expression at the end to
7491
- // preserve ordering.
7492
- if (subExpr != E)
7493
- diagnosedError |= diagnoseExprFailures (subExpr);
7494
- return subExpr;
7495
- });
7496
-
7497
- diagnosedError |= diagnoseExprFailures (E);
7498
- return diagnosedError;
7530
+ DiagnosticWalker diagnostics (E, solution);
7531
+ E->walk (diagnostics);
7532
+ return diagnostics.hadErrors ();
7499
7533
}
7500
7534
7501
7535
// / Apply a given solution to the expression, producing a fully
0 commit comments