@@ -7661,44 +7661,78 @@ Expr *ConstraintSystem::coerceToRValue(Expr *expr) {
7661
7661
// / Emit the fixes computed as part of the solution, returning true if we were
7662
7662
// / able to emit an error message, or false if none of the fixits worked out.
7663
7663
bool ConstraintSystem::applySolutionFixes (Expr *E, const Solution &solution) {
7664
- llvm::SmallDenseMap<Expr *, SmallVector<const ConstraintFix *, 4 >>
7665
- fixesPerExpr;
7666
-
7664
+ // First transfer all of the deduced information back
7665
+ // to the constraint system.
7667
7666
applySolution (solution);
7668
7667
7669
- for (auto *fix : solution.Fixes )
7670
- fixesPerExpr[fix->getAnchor ()].push_back (fix);
7668
+ class DiagnosticWalker : public ASTWalker {
7669
+ Expr *root;
7670
+ const Solution &solution;
7671
+ llvm::SmallDenseMap<Expr *, SmallVector<ConstraintFix *, 4 >> fixesPerExpr;
7671
7672
7672
- auto diagnoseExprFailures = [&](Expr *expr) -> bool {
7673
- auto fixes = fixesPerExpr.find (expr);
7674
- if (fixes == fixesPerExpr.end ())
7675
- return false ;
7673
+ // / Determines whether any error have been diagnosed while
7674
+ // / trying to apply fixes associated with a given solution.
7675
+ bool DiagnosedAnyErrors = false ;
7676
+
7677
+ public:
7678
+ DiagnosticWalker (Expr *expr, const Solution &solution)
7679
+ : root(expr), solution(solution) {
7680
+ for (auto *fix : solution.Fixes )
7681
+ fixesPerExpr[fix->getAnchor ()].push_back (fix);
7682
+ }
7683
+
7684
+ std::pair<bool , Expr *> walkToExprPre (Expr *E) override {
7685
+ // Diagnose root expression last.
7686
+ if (E == root)
7687
+ return {true , E};
7688
+
7689
+ if (auto *closure = dyn_cast<ClosureExpr>(E)) {
7690
+ auto result = solution.builderTransformedClosures .find (closure);
7691
+ if (result != solution.builderTransformedClosures .end ()) {
7692
+ auto *transformedExpr = result->second .second ;
7693
+ // Since this closure has been transformed into something
7694
+ // else let's look inside transformed expression instead.
7695
+ return {true , transformedExpr};
7696
+ }
7697
+ }
7676
7698
7677
- bool diagnosedError = false ;
7678
- for ( const auto *fix : fixes-> second ) {
7679
- auto diagnosed = fix-> diagnose (E);
7699
+ diagnose (E) ;
7700
+ return { true , E};
7701
+ }
7680
7702
7681
- if (fix->isWarning ()) {
7682
- assert (diagnosed && " warnings should always be diagnosed" );
7683
- (void )diagnosed;
7684
- } else {
7685
- diagnosedError |= diagnosed;
7703
+ Expr *walkToExprPost (Expr *E) override {
7704
+ if (E == root)
7705
+ diagnose (E);
7706
+ return E;
7707
+ }
7708
+
7709
+ std::pair<bool , Stmt *> walkToStmtPre (Stmt *S) override {
7710
+ return {true , S};
7711
+ }
7712
+
7713
+ bool hadErrors () const { return DiagnosedAnyErrors; }
7714
+
7715
+ private:
7716
+ void diagnose (Expr *E) {
7717
+ auto fixes = fixesPerExpr.find (E);
7718
+ if (fixes == fixesPerExpr.end ())
7719
+ return ;
7720
+
7721
+ for (const auto *fix : fixes->second ) {
7722
+ auto diagnosed = fix->diagnose (root);
7723
+ if (fix->isWarning ()) {
7724
+ assert (diagnosed && " warnings should always be diagnosed" );
7725
+ (void )diagnosed;
7726
+ } else {
7727
+ DiagnosedAnyErrors |= diagnosed;
7728
+ }
7686
7729
}
7687
7730
}
7688
- return diagnosedError;
7689
7731
};
7690
7732
7691
- bool diagnosedError = false ;
7692
- E->forEachChildExpr ([&](Expr *subExpr) -> Expr * {
7693
- // Diagnose root expression at the end to
7694
- // preserve ordering.
7695
- if (subExpr != E)
7696
- diagnosedError |= diagnoseExprFailures (subExpr);
7697
- return subExpr;
7698
- });
7699
-
7700
- diagnosedError |= diagnoseExprFailures (E);
7701
- return diagnosedError;
7733
+ DiagnosticWalker diagnostics (E, solution);
7734
+ E->walk (diagnostics);
7735
+ return diagnostics.hadErrors ();
7702
7736
}
7703
7737
7704
7738
// / Apply a given solution to the expression, producing a fully
0 commit comments