@@ -1374,9 +1374,10 @@ Optional<BraceStmt *> TypeChecker::applyFunctionBuilderBodyTransform(
13741374 // If we encountered an error or there was an explicit result type,
13751375 // bail out and report that to the caller.
13761376 auto &ctx = func->getASTContext ();
1377- auto request = PreCheckFunctionBuilderRequest{func, func->getBody ()};
1378- switch (evaluateOrDefault (
1379- ctx.evaluator , request, FunctionBuilderBodyPreCheck::Error)) {
1377+ auto request = PreCheckFunctionBuilderRequest{func, func->getBody (),
1378+ /* suppressDiagnostics=*/ false };
1379+ switch (evaluateOrDefault (ctx.evaluator , request,
1380+ FunctionBuilderBodyPreCheck::Error)) {
13801381 case FunctionBuilderBodyPreCheck::Okay:
13811382 // If the pre-check was okay, apply the function-builder transform.
13821383 break ;
@@ -1524,16 +1525,27 @@ ConstraintSystem::matchFunctionBuilder(
15241525
15251526 // Pre-check the body: pre-check any expressions in it and look
15261527 // for return statements.
1527- auto request = PreCheckFunctionBuilderRequest{fn, fn.getBody ()};
1528+ auto request = PreCheckFunctionBuilderRequest{fn, fn.getBody (),
1529+ /* SuppressDiagnostics=*/ true };
15281530 switch (evaluateOrDefault (getASTContext ().evaluator , request,
15291531 FunctionBuilderBodyPreCheck::Error)) {
15301532 case FunctionBuilderBodyPreCheck::Okay:
15311533 // If the pre-check was okay, apply the function-builder transform.
15321534 break ;
15331535
1534- case FunctionBuilderBodyPreCheck::Error:
1535- // If the pre-check had an error, flag that.
1536+ case FunctionBuilderBodyPreCheck::Error: {
1537+ if (!shouldAttemptFixes ())
1538+ return getTypeMatchFailure (locator);
1539+
1540+ if (auto *closure =
1541+ dyn_cast_or_null<ClosureExpr>(fn.getAbstractClosureExpr ())) {
1542+ auto failed = recordFix (IgnoreInvalidFunctionBuilderBody::create (
1543+ *this , getConstraintLocator (closure)));
1544+ return failed ? getTypeMatchFailure (locator) : getTypeMatchSuccess ();
1545+ }
1546+
15361547 return getTypeMatchFailure (locator);
1548+ }
15371549
15381550 case FunctionBuilderBodyPreCheck::HasReturnStmt:
15391551 // If the body has a return statement, suppress the transform but
@@ -1626,14 +1638,17 @@ namespace {
16261638class PreCheckFunctionBuilderApplication : public ASTWalker {
16271639 AnyFunctionRef Fn;
16281640 bool SkipPrecheck = false ;
1641+ bool SuppressDiagnostics = false ;
16291642 std::vector<ReturnStmt *> ReturnStmts;
16301643 bool HasError = false ;
16311644
16321645 bool hasReturnStmt () const { return !ReturnStmts.empty (); }
16331646
16341647public:
1635- PreCheckFunctionBuilderApplication (AnyFunctionRef fn, bool skipPrecheck)
1636- : Fn(fn), SkipPrecheck(skipPrecheck) {}
1648+ PreCheckFunctionBuilderApplication (AnyFunctionRef fn, bool skipPrecheck,
1649+ bool suppressDiagnostics)
1650+ : Fn(fn), SkipPrecheck(skipPrecheck),
1651+ SuppressDiagnostics (suppressDiagnostics) {}
16371652
16381653 const std::vector<ReturnStmt *> getReturnStmts () const { return ReturnStmts; }
16391654
@@ -1657,16 +1672,28 @@ class PreCheckFunctionBuilderApplication : public ASTWalker {
16571672 }
16581673
16591674 std::pair<bool , Expr *> walkToExprPre (Expr *E) override {
1675+ if (SkipPrecheck)
1676+ return std::make_pair (false , E);
1677+
16601678 // Pre-check the expression. If this fails, abort the walk immediately.
16611679 // Otherwise, replace the expression with the result of pre-checking.
16621680 // In either case, don't recurse into the expression.
1663- if (!SkipPrecheck &&
1664- ConstraintSystem::preCheckExpression (E, /* DC*/ Fn.getAsDeclContext ())) {
1665- HasError = true ;
1666- return std::make_pair (false , nullptr );
1667- }
1681+ {
1682+ auto *DC = Fn.getAsDeclContext ();
1683+ auto &diagEngine = DC->getASTContext ().Diags ;
1684+
1685+ // Suppress any diangostics which could be produced by this expression.
1686+ DiagnosticTransaction transaction (diagEngine);
16681687
1669- return std::make_pair (false , E);
1688+ HasError |= ConstraintSystem::preCheckExpression (
1689+ E, DC, /* replaceInvalidRefsWithErrors=*/ false );
1690+ HasError |= transaction.hasDiagnostics ();
1691+
1692+ if (SuppressDiagnostics)
1693+ transaction.abort ();
1694+
1695+ return std::make_pair (false , HasError ? nullptr : E);
1696+ }
16701697 }
16711698
16721699 std::pair<bool , Stmt *> walkToStmtPre (Stmt *S) override {
@@ -1692,18 +1719,20 @@ class PreCheckFunctionBuilderApplication : public ASTWalker {
16921719
16931720FunctionBuilderBodyPreCheck
16941721PreCheckFunctionBuilderRequest::evaluate (Evaluator &eval, AnyFunctionRef fn,
1695- BraceStmt *body) const {
1722+ BraceStmt *body,
1723+ bool suppressDiagnostics) const {
16961724 // NOTE: 'body' is passed only for the request evaluater caching key.
16971725 // Since source tooling (e.g. code completion) might replace the body,
16981726 // the function alone is not sufficient for the key.
16991727 assert (fn.getBody () == body &&
17001728 " body must be the current body of the function" );
17011729
1702- return PreCheckFunctionBuilderApplication (fn, false ).run ();
1730+ return PreCheckFunctionBuilderApplication (fn, false , suppressDiagnostics ).run ();
17031731}
17041732
17051733std::vector<ReturnStmt *> TypeChecker::findReturnStatements (AnyFunctionRef fn) {
1706- PreCheckFunctionBuilderApplication precheck (fn, true );
1734+ PreCheckFunctionBuilderApplication precheck (fn, /* skipPreCheck=*/ true ,
1735+ /* SuppressDiagnostics=*/ true );
17071736 (void )precheck.run ();
17081737 return precheck.getReturnStmts ();
17091738}
0 commit comments