Skip to content

Commit c7ea672

Browse files
committed
[NFC] AST, Sema: Internalize BraceHasReturnRequest evaluation in AnyFunctionRef method
1 parent 3742da7 commit c7ea672

File tree

6 files changed

+47
-7
lines changed

6 files changed

+47
-7
lines changed

include/swift/AST/AnyFunctionRef.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,13 @@ class AnyFunctionRef {
153153
llvm_unreachable("autoclosures don't have statement bodies");
154154
}
155155

156+
/// Returns a boolean value indicating whether the body, if any, contains
157+
/// an explicit `return` statement.
158+
///
159+
/// \returns `true` if the body contains an explicit `return` statement,
160+
/// `false` otherwise.
161+
bool bodyHasExplicitReturnStmt() const;
162+
156163
DeclContext *getAsDeclContext() const {
157164
if (auto *AFD = TheFunction.dyn_cast<AbstractFunctionDecl *>())
158165
return AFD;

include/swift/AST/Decl.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7675,6 +7675,13 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
76757675
/// parsed.
76767676
bool hasBody() const;
76777677

7678+
/// Returns a boolean value indicating whether the body, if any, contains
7679+
/// an explicit `return` statement.
7680+
///
7681+
/// \returns `true` if the body contains an explicit `return` statement,
7682+
/// `false` otherwise.
7683+
bool bodyHasExplicitReturnStmt() const;
7684+
76787685
/// Returns true if the text of this function's body can be retrieved either
76797686
/// by extracting the text from the source buffer or reading the inlinable
76807687
/// body from a deserialized swiftmodule.

include/swift/AST/Expr.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4051,6 +4051,13 @@ class AbstractClosureExpr : public DeclContext, public Expr {
40514051
/// returns nullptr if the closure doesn't have a body
40524052
BraceStmt *getBody() const;
40534053

4054+
/// Returns a boolean value indicating whether the body, if any, contains
4055+
/// an explicit `return` statement.
4056+
///
4057+
/// \returns `true` if the body contains an explicit `return` statement,
4058+
/// `false` otherwise.
4059+
bool bodyHasExplicitReturnStmt() const;
4060+
40544061
ActorIsolation getActorIsolation() const {
40554062
return actorIsolation;
40564063
}

lib/AST/Decl.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9356,6 +9356,11 @@ bool AbstractFunctionDecl::hasBody() const {
93569356
}
93579357
}
93589358

9359+
bool AbstractFunctionDecl::bodyHasExplicitReturnStmt() const {
9360+
return AnyFunctionRef(const_cast<AbstractFunctionDecl *>(this))
9361+
.bodyHasExplicitReturnStmt();
9362+
}
9363+
93599364
/// Expand all preamble macros attached to the given function declaration.
93609365
static std::vector<ASTNode> expandPreamble(AbstractFunctionDecl *func) {
93619366
std::vector<ASTNode> preamble;

lib/AST/Expr.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1962,6 +1962,11 @@ BraceStmt * AbstractClosureExpr::getBody() const {
19621962
llvm_unreachable("Unknown closure expression");
19631963
}
19641964

1965+
bool AbstractClosureExpr::bodyHasExplicitReturnStmt() const {
1966+
return AnyFunctionRef(const_cast<AbstractClosureExpr *>(this))
1967+
.bodyHasExplicitReturnStmt();
1968+
}
1969+
19651970
Type AbstractClosureExpr::getResultType(
19661971
llvm::function_ref<Type(Expr *)> getType) const {
19671972
auto *E = const_cast<AbstractClosureExpr *>(this);

lib/Sema/BuilderTransform.cpp

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -918,13 +918,9 @@ std::optional<BraceStmt *>
918918
TypeChecker::applyResultBuilderBodyTransform(FuncDecl *func, Type builderType) {
919919
// First look for any return statements, and bail if we have any.
920920
auto &ctx = func->getASTContext();
921-
if (evaluateOrDefault(ctx.evaluator, BraceHasReturnRequest{func->getBody()},
922-
false)) {
921+
if (auto returnStmts = findReturnStatements(func); !returnStmts.empty()) {
923922
// One or more explicit 'return' statements were encountered, which
924923
// disables the result builder transform. Warn when we do this.
925-
auto returnStmts = findReturnStatements(func);
926-
assert(!returnStmts.empty());
927-
928924
ctx.Diags.diagnose(
929925
returnStmts.front()->getReturnLoc(),
930926
diag::result_builder_disabled_by_return_warn, builderType);
@@ -1126,8 +1122,7 @@ ConstraintSystem::matchResultBuilder(AnyFunctionRef fn, Type builderType,
11261122
// not apply the result builder transform if it contained an explicit return.
11271123
// To maintain source compatibility, we still need to check for HasReturnStmt.
11281124
// https://github.com/apple/swift/issues/64332.
1129-
if (evaluateOrDefault(getASTContext().evaluator,
1130-
BraceHasReturnRequest{fn.getBody()}, false)) {
1125+
if (fn.bodyHasExplicitReturnStmt()) {
11311126
// Diagnostic mode means that solver couldn't reach any viable
11321127
// solution, so let's diagnose presence of a `return` statement
11331128
// in the closure body.
@@ -1276,7 +1271,21 @@ bool BraceHasReturnRequest::evaluate(Evaluator &evaluator,
12761271
return !ReturnStmtFinder::find(BS).empty();
12771272
}
12781273

1274+
bool AnyFunctionRef::bodyHasExplicitReturnStmt() const {
1275+
auto *body = getBody();
1276+
if (!body) {
1277+
return false;
1278+
}
1279+
1280+
auto &ctx = getAsDeclContext()->getASTContext();
1281+
return evaluateOrDefault(ctx.evaluator, BraceHasReturnRequest{body}, false);
1282+
}
1283+
12791284
std::vector<ReturnStmt *> TypeChecker::findReturnStatements(AnyFunctionRef fn) {
1285+
if (!fn.bodyHasExplicitReturnStmt()) {
1286+
return std::vector<ReturnStmt *>();
1287+
}
1288+
12801289
return ReturnStmtFinder::find(fn.getBody());
12811290
}
12821291

0 commit comments

Comments
 (0)