diff --git a/include/swift/AST/TypeCheckRequests.h b/include/swift/AST/TypeCheckRequests.h index 2f57ca2c6fd..fc3572723cb 100644 --- a/include/swift/AST/TypeCheckRequests.h +++ b/include/swift/AST/TypeCheckRequests.h @@ -1843,6 +1843,7 @@ public: struct PreCheckFunctionBuilderDescriptor { AnyFunctionRef Fn; + bool SuppressDiagnostics; private: // NOTE: Since source tooling (e.g. code completion) might replace the body, @@ -1852,8 +1853,8 @@ private: BraceStmt *Body; public: - PreCheckFunctionBuilderDescriptor(AnyFunctionRef Fn) - : Fn(Fn), Body(Fn.getBody()) {} + PreCheckFunctionBuilderDescriptor(AnyFunctionRef Fn, bool suppressDiagnostics) + : Fn(Fn), SuppressDiagnostics(suppressDiagnostics), Body(Fn.getBody()) {} friend llvm::hash_code hash_value(const PreCheckFunctionBuilderDescriptor &owner) { diff --git a/lib/Sema/BuilderTransform.cpp b/lib/Sema/BuilderTransform.cpp index a0b8257689f..c14cb8e257f 100644 --- a/lib/Sema/BuilderTransform.cpp +++ b/lib/Sema/BuilderTransform.cpp @@ -1485,9 +1485,11 @@ Optional TypeChecker::applyFunctionBuilderBodyTransform( // If we encountered an error or there was an explicit result type, // bail out and report that to the caller. auto &ctx = func->getASTContext(); - auto request = PreCheckFunctionBuilderRequest{AnyFunctionRef(func)}; - switch (evaluateOrDefault( - ctx.evaluator, request, FunctionBuilderBodyPreCheck::Error)) { + auto request = + PreCheckFunctionBuilderRequest{{AnyFunctionRef(func), + /*SuppressDiagnostics=*/false}}; + switch (evaluateOrDefault(ctx.evaluator, request, + FunctionBuilderBodyPreCheck::Error)) { case FunctionBuilderBodyPreCheck::Okay: // If the pre-check was okay, apply the function-builder transform. break; @@ -1619,7 +1621,8 @@ ConstraintSystem::matchFunctionBuilder( // Pre-check the body: pre-check any expressions in it and look // for return statements. - auto request = PreCheckFunctionBuilderRequest{fn}; + auto request = + PreCheckFunctionBuilderRequest{{fn, /*SuppressDiagnostics=*/false}}; switch (evaluateOrDefault(getASTContext().evaluator, request, FunctionBuilderBodyPreCheck::Error)) { case FunctionBuilderBodyPreCheck::Okay: @@ -1705,14 +1708,17 @@ namespace { class PreCheckFunctionBuilderApplication : public ASTWalker { AnyFunctionRef Fn; bool SkipPrecheck = false; + bool SuppressDiagnostics = false; std::vector ReturnStmts; bool HasError = false; bool hasReturnStmt() const { return !ReturnStmts.empty(); } public: - PreCheckFunctionBuilderApplication(AnyFunctionRef fn, bool skipPrecheck) - : Fn(fn), SkipPrecheck(skipPrecheck) {} + PreCheckFunctionBuilderApplication(AnyFunctionRef fn, bool skipPrecheck, + bool suppressDiagnostics) + : Fn(fn), SkipPrecheck(skipPrecheck), + SuppressDiagnostics(suppressDiagnostics) {} const std::vector getReturnStmts() const { return ReturnStmts; } @@ -1753,7 +1759,9 @@ public: E, DC, /*replaceInvalidRefsWithErrors=*/false); HasError |= transaction.hasDiagnostics(); - transaction.abort(); + if (SuppressDiagnostics) + transaction.abort(); + return std::make_pair(false, HasError ? nullptr : E); } } @@ -1788,11 +1796,15 @@ FunctionBuilderBodyPreCheck PreCheckFunctionBuilderRequest::evaluate( owner.Fn.getAbstractClosureExpr())) skipPrecheck = shouldTypeCheckInEnclosingExpression(closure); - return PreCheckFunctionBuilderApplication(owner.Fn, false).run(); + return PreCheckFunctionBuilderApplication( + owner.Fn, /*skipPrecheck=*/false, + /*suppressDiagnostics=*/owner.SuppressDiagnostics) + .run(); } std::vector TypeChecker::findReturnStatements(AnyFunctionRef fn) { - PreCheckFunctionBuilderApplication precheck(fn, true); + PreCheckFunctionBuilderApplication precheck(fn, /*skipPreCheck=*/true, + /*SuppressDiagnostics=*/true); (void)precheck.run(); return precheck.getReturnStmts(); }