@@ -7413,44 +7413,78 @@ Expr *ConstraintSystem::coerceToRValue(Expr *expr) {
7413
7413
// / Emit the fixes computed as part of the solution, returning true if we were
7414
7414
// / able to emit an error message, or false if none of the fixits worked out.
7415
7415
bool ConstraintSystem::applySolutionFixes (Expr *E, const Solution &solution) {
7416
- llvm::SmallDenseMap<Expr *, SmallVector<const ConstraintFix *, 4 >>
7417
- fixesPerExpr;
7418
-
7416
+ // First transfer all of the deduced information back
7417
+ // to the constraint system.
7419
7418
applySolution (solution);
7420
7419
7421
- for (auto *fix : solution.Fixes )
7422
- fixesPerExpr[fix->getAnchor ()].push_back (fix);
7420
+ class DiagnosticWalker : public ASTWalker {
7421
+ Expr *root;
7422
+ const Solution &solution;
7423
+ llvm::SmallDenseMap<Expr *, SmallVector<ConstraintFix *, 4 >> fixesPerExpr;
7423
7424
7424
- auto diagnoseExprFailures = [&](Expr *expr) -> bool {
7425
- auto fixes = fixesPerExpr.find (expr);
7426
- if (fixes == fixesPerExpr.end ())
7427
- return false ;
7425
+ // / Determines whether any error have been diagnosed while
7426
+ // / trying to apply fixes associated with a given solution.
7427
+ bool DiagnosedAnyErrors = false ;
7428
+
7429
+ public:
7430
+ DiagnosticWalker (Expr *expr, const Solution &solution)
7431
+ : root(expr), solution(solution) {
7432
+ for (auto *fix : solution.Fixes )
7433
+ fixesPerExpr[fix->getAnchor ()].push_back (fix);
7434
+ }
7435
+
7436
+ std::pair<bool , Expr *> walkToExprPre (Expr *E) override {
7437
+ // Diagnose root expression last.
7438
+ if (E == root)
7439
+ return {true , E};
7440
+
7441
+ if (auto *closure = dyn_cast<ClosureExpr>(E)) {
7442
+ auto result = solution.builderTransformedClosures .find (closure);
7443
+ if (result != solution.builderTransformedClosures .end ()) {
7444
+ auto *transformedExpr = result->second .second ;
7445
+ // Since this closure has been transformed into something
7446
+ // else let's look inside transformed expression instead.
7447
+ return {true , transformedExpr};
7448
+ }
7449
+ }
7428
7450
7429
- bool diagnosedError = false ;
7430
- for ( const auto *fix : fixes-> second ) {
7431
- auto diagnosed = fix-> diagnose (E);
7451
+ diagnose (E) ;
7452
+ return { true , E};
7453
+ }
7432
7454
7433
- if (fix->isWarning ()) {
7434
- assert (diagnosed && " warnings should always be diagnosed" );
7435
- (void )diagnosed;
7436
- } else {
7437
- diagnosedError |= diagnosed;
7455
+ Expr *walkToExprPost (Expr *E) override {
7456
+ if (E == root)
7457
+ diagnose (E);
7458
+ return E;
7459
+ }
7460
+
7461
+ std::pair<bool , Stmt *> walkToStmtPre (Stmt *S) override {
7462
+ return {true , S};
7463
+ }
7464
+
7465
+ bool hadErrors () const { return DiagnosedAnyErrors; }
7466
+
7467
+ private:
7468
+ void diagnose (Expr *E) {
7469
+ auto fixes = fixesPerExpr.find (E);
7470
+ if (fixes == fixesPerExpr.end ())
7471
+ return ;
7472
+
7473
+ for (const auto *fix : fixes->second ) {
7474
+ auto diagnosed = fix->diagnose (root);
7475
+ if (fix->isWarning ()) {
7476
+ assert (diagnosed && " warnings should always be diagnosed" );
7477
+ (void )diagnosed;
7478
+ } else {
7479
+ DiagnosedAnyErrors |= diagnosed;
7480
+ }
7438
7481
}
7439
7482
}
7440
- return diagnosedError;
7441
7483
};
7442
7484
7443
- bool diagnosedError = false ;
7444
- E->forEachChildExpr ([&](Expr *subExpr) -> Expr * {
7445
- // Diagnose root expression at the end to
7446
- // preserve ordering.
7447
- if (subExpr != E)
7448
- diagnosedError |= diagnoseExprFailures (subExpr);
7449
- return subExpr;
7450
- });
7451
-
7452
- diagnosedError |= diagnoseExprFailures (E);
7453
- return diagnosedError;
7485
+ DiagnosticWalker diagnostics (E, solution);
7486
+ E->walk (diagnostics);
7487
+ return diagnostics.hadErrors ();
7454
7488
}
7455
7489
7456
7490
// / Apply a given solution to the expression, producing a fully
0 commit comments