@@ -1489,9 +1489,11 @@ Optional<BraceStmt *> TypeChecker::applyFunctionBuilderBodyTransform(
14891489 // If we encountered an error or there was an explicit result type,
14901490 // bail out and report that to the caller.
14911491 auto &ctx = func->getASTContext ();
1492- auto request = PreCheckFunctionBuilderRequest{AnyFunctionRef (func)};
1493- switch (evaluateOrDefault (
1494- ctx.evaluator , request, FunctionBuilderBodyPreCheck::Error)) {
1492+ auto request =
1493+ PreCheckFunctionBuilderRequest{{AnyFunctionRef (func),
1494+ /* SuppressDiagnostics=*/ false }};
1495+ switch (evaluateOrDefault (ctx.evaluator , request,
1496+ FunctionBuilderBodyPreCheck::Error)) {
14951497 case FunctionBuilderBodyPreCheck::Okay:
14961498 // If the pre-check was okay, apply the function-builder transform.
14971499 break ;
@@ -1623,16 +1625,24 @@ ConstraintSystem::matchFunctionBuilder(
16231625
16241626 // Pre-check the body: pre-check any expressions in it and look
16251627 // for return statements.
1626- auto request = PreCheckFunctionBuilderRequest{fn};
1628+ auto request =
1629+ PreCheckFunctionBuilderRequest{{fn, /* SuppressDiagnostics=*/ true }};
16271630 switch (evaluateOrDefault (getASTContext ().evaluator , request,
16281631 FunctionBuilderBodyPreCheck::Error)) {
16291632 case FunctionBuilderBodyPreCheck::Okay:
16301633 // If the pre-check was okay, apply the function-builder transform.
16311634 break ;
16321635
1633- case FunctionBuilderBodyPreCheck::Error:
1634- // If the pre-check had an error, flag that.
1635- return getTypeMatchFailure (locator);
1636+ case FunctionBuilderBodyPreCheck::Error: {
1637+ if (!shouldAttemptFixes ())
1638+ return getTypeMatchFailure (locator);
1639+
1640+ if (recordFix (IgnoreInvalidFunctionBuilderBody::create (
1641+ *this , getConstraintLocator (fn.getBody ()))))
1642+ return getTypeMatchFailure (locator);
1643+
1644+ return getTypeMatchSuccess ();
1645+ }
16361646
16371647 case FunctionBuilderBodyPreCheck::HasReturnStmt:
16381648 // If the body has a return statement, suppress the transform but
@@ -1709,14 +1719,17 @@ namespace {
17091719class PreCheckFunctionBuilderApplication : public ASTWalker {
17101720 AnyFunctionRef Fn;
17111721 bool SkipPrecheck = false ;
1722+ bool SuppressDiagnostics = false ;
17121723 std::vector<ReturnStmt *> ReturnStmts;
17131724 bool HasError = false ;
17141725
17151726 bool hasReturnStmt () const { return !ReturnStmts.empty (); }
17161727
17171728public:
1718- PreCheckFunctionBuilderApplication (AnyFunctionRef fn, bool skipPrecheck)
1719- : Fn(fn), SkipPrecheck(skipPrecheck) {}
1729+ PreCheckFunctionBuilderApplication (AnyFunctionRef fn, bool skipPrecheck,
1730+ bool suppressDiagnostics)
1731+ : Fn(fn), SkipPrecheck(skipPrecheck),
1732+ SuppressDiagnostics (suppressDiagnostics) {}
17201733
17211734 const std::vector<ReturnStmt *> getReturnStmts () const { return ReturnStmts; }
17221735
@@ -1740,16 +1753,28 @@ class PreCheckFunctionBuilderApplication : public ASTWalker {
17401753 }
17411754
17421755 std::pair<bool , Expr *> walkToExprPre (Expr *E) override {
1756+ if (SkipPrecheck)
1757+ return std::make_pair (false , E);
1758+
17431759 // Pre-check the expression. If this fails, abort the walk immediately.
17441760 // Otherwise, replace the expression with the result of pre-checking.
17451761 // In either case, don't recurse into the expression.
1746- if (!SkipPrecheck &&
1747- ConstraintSystem::preCheckExpression (E, /* DC*/ Fn.getAsDeclContext ())) {
1748- HasError = true ;
1749- return std::make_pair (false , nullptr );
1750- }
1762+ {
1763+ auto *DC = Fn.getAsDeclContext ();
1764+ auto &diagEngine = DC->getASTContext ().Diags ;
1765+
1766+ // Suppress any diangostics which could be produced by this expression.
1767+ DiagnosticTransaction transaction (diagEngine);
17511768
1752- return std::make_pair (false , E);
1769+ HasError |= ConstraintSystem::preCheckExpression (
1770+ E, DC, /* replaceInvalidRefsWithErrors=*/ false );
1771+ HasError |= transaction.hasDiagnostics ();
1772+
1773+ if (SuppressDiagnostics)
1774+ transaction.abort ();
1775+
1776+ return std::make_pair (false , HasError ? nullptr : E);
1777+ }
17531778 }
17541779
17551780 std::pair<bool , Stmt *> walkToStmtPre (Stmt *S) override {
@@ -1782,11 +1807,15 @@ FunctionBuilderBodyPreCheck PreCheckFunctionBuilderRequest::evaluate(
17821807 owner.Fn .getAbstractClosureExpr ()))
17831808 skipPrecheck = shouldTypeCheckInEnclosingExpression (closure);
17841809
1785- return PreCheckFunctionBuilderApplication (owner.Fn , false ).run ();
1810+ return PreCheckFunctionBuilderApplication (
1811+ owner.Fn , /* skipPrecheck=*/ false ,
1812+ /* suppressDiagnostics=*/ owner.SuppressDiagnostics )
1813+ .run ();
17861814}
17871815
17881816std::vector<ReturnStmt *> TypeChecker::findReturnStatements (AnyFunctionRef fn) {
1789- PreCheckFunctionBuilderApplication precheck (fn, true );
1817+ PreCheckFunctionBuilderApplication precheck (fn, /* skipPreCheck=*/ true ,
1818+ /* SuppressDiagnostics=*/ true );
17901819 (void )precheck.run ();
17911820 return precheck.getReturnStmts ();
17921821}
0 commit comments