Skip to content

Commit aa695c3

Browse files
authored
Merge pull request #65347 from hamishknight/poundland-5.9
2 parents 76e21ad + 9a22f72 commit aa695c3

File tree

17 files changed

+889
-99
lines changed

17 files changed

+889
-99
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1143,6 +1143,9 @@ ERROR(single_value_stmt_must_be_unlabeled,none,
11431143
ERROR(if_expr_must_be_syntactically_exhaustive,none,
11441144
"'if' must have an unconditional 'else' to be used as expression",
11451145
())
1146+
ERROR(single_value_stmt_branch_empty,none,
1147+
"expected expression in branch of '%0' expression",
1148+
(StmtKind))
11461149
ERROR(single_value_stmt_branch_must_end_in_throw,none,
11471150
"non-expression branch of '%0' expression may only end with a 'throw'",
11481151
(StmtKind))

include/swift/AST/Stmt.h

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -212,9 +212,20 @@ class BraceStmt final : public Stmt,
212212

213213
ASTNode findAsyncNode();
214214

215-
/// If this brace is wrapping a single expression, returns it. Otherwise
216-
/// returns \c nullptr.
217-
Expr *getSingleExpressionElement() const;
215+
/// If this brace contains a single ASTNode, or a \c #if that has a single active
216+
/// element, returns it. This will always be the last element of the brace.
217+
/// Otherwise returns \c nullptr.
218+
ASTNode getSingleActiveElement() const;
219+
220+
/// If this brace is wrapping a single active expression, returns it. This
221+
/// includes both a single expression element, or a single expression in an
222+
/// active \c #if. Otherwise returns \c nullptr.
223+
Expr *getSingleActiveExpression() const;
224+
225+
/// If this brace is wrapping a single active statement, returns it. This
226+
/// includes both a single statement element, or a single statement in an
227+
/// active \c #if. Otherwise returns \c nullptr.
228+
Stmt *getSingleActiveStatement() const;
218229

219230
static bool classof(const Stmt *S) { return S->getKind() == StmtKind::Brace; }
220231
};

include/swift/Parse/Parser.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -691,11 +691,6 @@ class Parser {
691691
/// \param DiagText name for the string literal in the diagnostic.
692692
Optional<StringRef>
693693
getStringLiteralIfNotInterpolated(SourceLoc Loc, StringRef DiagText);
694-
695-
/// Returns true when body elements are eligible as single-expression implicit returns.
696-
///
697-
/// \param Body elements to search for implicit single-expression returns.
698-
bool shouldReturnSingleExpressionElement(ArrayRef<ASTNode> Body);
699694

700695
/// Returns true to indicate that experimental concurrency syntax should be
701696
/// parsed if the parser is generating only a syntax tree or if the user has

lib/AST/Expr.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2524,11 +2524,7 @@ SingleValueStmtExpr *SingleValueStmtExpr::createWithWrappedBranches(
25242524
if (!BS)
25252525
continue;
25262526

2527-
auto elts = BS->getElements();
2528-
if (elts.size() != 1)
2529-
continue;
2530-
2531-
auto *S = elts.front().dyn_cast<Stmt *>();
2527+
auto *S = BS->getSingleActiveStatement();
25322528
if (!S)
25332529
continue;
25342530

@@ -2615,7 +2611,7 @@ ArrayRef<Expr *> SingleValueStmtExpr::getSingleExprBranches(
26152611
auto *BS = dyn_cast<BraceStmt>(branch);
26162612
if (!BS)
26172613
continue;
2618-
if (auto *E = BS->getSingleExpressionElement())
2614+
if (auto *E = BS->getSingleActiveExpression())
26192615
scratch.push_back(E);
26202616
}
26212617
return scratch;

lib/AST/Stmt.cpp

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -299,11 +299,37 @@ ASTNode BraceStmt::findAsyncNode() {
299299
return asyncFinder.getAsyncNode();
300300
}
301301

302-
Expr *BraceStmt::getSingleExpressionElement() const {
303-
if (getElements().size() != 1)
304-
return nullptr;
302+
static bool hasSingleActiveElement(ArrayRef<ASTNode> elts) {
303+
while (true) {
304+
// Single element brace.
305+
if (elts.size() == 1)
306+
return true;
307+
308+
// See if we have a #if as the first element of a 2 element brace, if so we
309+
// can recuse into its active clause. If so, the second element will be the
310+
// active element.
311+
if (elts.size() == 2) {
312+
if (auto *D = elts.front().dyn_cast<Decl *>()) {
313+
if (auto *ICD = dyn_cast<IfConfigDecl>(D)) {
314+
elts = ICD->getActiveClauseElements();
315+
continue;
316+
}
317+
}
318+
}
319+
return false;
320+
}
321+
}
322+
323+
ASTNode BraceStmt::getSingleActiveElement() const {
324+
return hasSingleActiveElement(getElements()) ? getLastElement() : nullptr;
325+
}
326+
327+
Expr *BraceStmt::getSingleActiveExpression() const {
328+
return getSingleActiveElement().dyn_cast<Expr *>();
329+
}
305330

306-
return getElements()[0].dyn_cast<Expr *>();
331+
Stmt *BraceStmt::getSingleActiveStatement() const {
332+
return getSingleActiveElement().dyn_cast<Stmt *>();
307333
}
308334

309335
IsSingleValueStmtResult Stmt::mayProduceSingleValue(Evaluator &eval) const {

lib/Parse/ParseDecl.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8097,8 +8097,7 @@ Parser::parseAbstractFunctionBodyImpl(AbstractFunctionDecl *AFD) {
80978097
AFD->setHasSingleExpressionBody(false);
80988098
AFD->setBodyParsed(BS, fp);
80998099

8100-
if (Parser::shouldReturnSingleExpressionElement(BS->getElements())) {
8101-
auto Element = BS->getLastElement();
8100+
if (auto Element = BS->getSingleActiveElement()) {
81028101
if (auto *stmt = Element.dyn_cast<Stmt *>()) {
81038102
if (isa<FuncDecl>(AFD)) {
81048103
if (auto *returnStmt = dyn_cast<ReturnStmt>(stmt)) {

lib/Parse/ParseExpr.cpp

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2902,37 +2902,36 @@ ParserResult<Expr> Parser::parseExprClosure() {
29022902
closure->setParameterList(params);
29032903
closure->setHasAnonymousClosureVars();
29042904
}
2905-
2905+
2906+
auto *BS = BraceStmt::create(Context, leftBrace, bodyElements, rightBrace);
2907+
29062908
// If the body consists of a single expression, turn it into a return
29072909
// statement.
29082910
bool hasSingleExpressionBody = false;
2909-
if (!missingRBrace &&
2910-
Parser::shouldReturnSingleExpressionElement(bodyElements)) {
2911-
auto Element = bodyElements.back();
2912-
2913-
if (Element.is<Stmt *>()) {
2914-
if (auto returnStmt = dyn_cast<ReturnStmt>(Element.get<Stmt *>())) {
2915-
hasSingleExpressionBody = true;
2916-
if (!returnStmt->hasResult()) {
2917-
auto returnExpr = TupleExpr::createEmpty(Context,
2918-
SourceLoc(),
2919-
SourceLoc(),
2920-
/*implicit*/true);
2921-
returnStmt->setResult(returnExpr);
2911+
if (!missingRBrace) {
2912+
if (auto Element = BS->getSingleActiveElement()) {
2913+
if (Element.is<Stmt *>()) {
2914+
if (auto returnStmt = dyn_cast<ReturnStmt>(Element.get<Stmt *>())) {
2915+
hasSingleExpressionBody = true;
2916+
if (!returnStmt->hasResult()) {
2917+
auto returnExpr = TupleExpr::createEmpty(Context,
2918+
SourceLoc(),
2919+
SourceLoc(),
2920+
/*implicit*/true);
2921+
returnStmt->setResult(returnExpr);
2922+
}
29222923
}
2924+
} else if (Element.is<Expr *>()) {
2925+
// Create the wrapping return.
2926+
hasSingleExpressionBody = true;
2927+
auto returnExpr = Element.get<Expr*>();
2928+
BS->setLastElement(new (Context) ReturnStmt(SourceLoc(), returnExpr));
29232929
}
2924-
} else if (Element.is<Expr *>()) {
2925-
// Create the wrapping return.
2926-
hasSingleExpressionBody = true;
2927-
auto returnExpr = Element.get<Expr*>();
2928-
bodyElements.back() = new (Context) ReturnStmt(SourceLoc(), returnExpr);
29292930
}
29302931
}
29312932

29322933
// Set the body of the closure.
2933-
closure->setBody(BraceStmt::create(Context, leftBrace, bodyElements,
2934-
rightBrace),
2935-
hasSingleExpressionBody);
2934+
closure->setBody(BS, hasSingleExpressionBody);
29362935

29372936
// If the closure includes a capture list, create an AST node for it as well.
29382937
Expr *result = closure;

lib/Parse/Parser.cpp

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1096,31 +1096,6 @@ Parser::getStringLiteralIfNotInterpolated(SourceLoc Loc,
10961096
Segments.front().Length));
10971097
}
10981098

1099-
bool Parser::shouldReturnSingleExpressionElement(ArrayRef<ASTNode> Body) {
1100-
// If the body consists of an #if declaration with a single
1101-
// expression active clause, find a single expression.
1102-
if (Body.size() == 2) {
1103-
if (auto *D = Body.front().dyn_cast<Decl *>()) {
1104-
// Step into nested active clause.
1105-
while (auto *ICD = dyn_cast<IfConfigDecl>(D)) {
1106-
auto ACE = ICD->getActiveClauseElements();
1107-
if (ACE.size() == 1) {
1108-
assert(Body.back() == ACE.back() &&
1109-
"active clause not found in body");
1110-
return true;
1111-
} else if (ACE.size() == 2) {
1112-
if (auto *ND = ACE.front().dyn_cast<Decl *>()) {
1113-
D = ND;
1114-
continue;
1115-
}
1116-
}
1117-
break;
1118-
}
1119-
}
1120-
}
1121-
return Body.size() == 1;
1122-
}
1123-
11241099
struct ParserUnit::Implementation {
11251100
LangOptions LangOpts;
11261101
TypeCheckerOptions TypeCheckerOpts;

lib/Sema/MiscDiagnostics.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3866,6 +3866,14 @@ class SingleValueStmtUsageChecker final : public ASTWalker {
38663866
break;
38673867
case IsSingleValueStmtResult::Kind::UnterminatedBranches: {
38683868
for (auto *branch : mayProduceSingleValue.getUnterminatedBranches()) {
3869+
if (auto *BS = dyn_cast<BraceStmt>(branch)) {
3870+
if (BS->empty()) {
3871+
Diags.diagnose(branch->getStartLoc(),
3872+
diag::single_value_stmt_branch_empty,
3873+
S->getKind());
3874+
continue;
3875+
}
3876+
}
38693877
Diags.diagnose(branch->getEndLoc(),
38703878
diag::single_value_stmt_branch_must_end_in_throw,
38713879
S->getKind());

lib/Sema/PreCheckExpr.cpp

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1354,15 +1354,13 @@ bool PreCheckExpression::walkToClosureExprPre(ClosureExpr *closure) {
13541354
// LeaveClosureBodiesUnchecked, as the closure may become a single expression
13551355
// closure.
13561356
auto *body = closure->getBody();
1357-
if (body->getNumElements() == 1) {
1358-
if (auto *S = body->getLastElement().dyn_cast<Stmt *>()) {
1359-
if (S->mayProduceSingleValue(Ctx)) {
1360-
auto *SVE = SingleValueStmtExpr::createWithWrappedBranches(
1361-
Ctx, S, /*DC*/ closure, /*mustBeExpr*/ false);
1362-
auto *RS = new (Ctx) ReturnStmt(SourceLoc(), SVE);
1363-
body->setLastElement(RS);
1364-
closure->setBody(body, /*isSingleExpression*/ true);
1365-
}
1357+
if (auto *S = body->getSingleActiveStatement()) {
1358+
if (S->mayProduceSingleValue(Ctx)) {
1359+
auto *SVE = SingleValueStmtExpr::createWithWrappedBranches(
1360+
Ctx, S, /*DC*/ closure, /*mustBeExpr*/ false);
1361+
auto *RS = new (Ctx) ReturnStmt(SourceLoc(), SVE);
1362+
body->setLastElement(RS);
1363+
closure->setBody(body, /*isSingleExpression*/ true);
13661364
}
13671365
}
13681366

lib/Sema/TypeCheckStmt.cpp

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2668,23 +2668,26 @@ TypeCheckFunctionBodyRequest::evaluate(Evaluator &evaluator,
26682668

26692669
body->walk(ContextualizeClosuresAndMacros(AFD));
26702670
}
2671-
} else if (func->hasSingleExpressionBody() &&
2672-
func->getResultInterfaceType()->isVoid()) {
2673-
// The function returns void. We don't need an explicit return, no matter
2674-
// what the type of the expression is. Take the inserted return back out.
2675-
body->setLastElement(func->getSingleExpressionBody());
2676-
} else if (func->getBody()->getNumElements() == 1 &&
2677-
!func->getResultInterfaceType()->isVoid()) {
2671+
} else {
2672+
if (func->hasSingleExpressionBody() &&
2673+
func->getResultInterfaceType()->isVoid()) {
2674+
// The function returns void. We don't need an explicit return, no
2675+
// matter what the type of the expression is. Take the inserted return
2676+
// back out.
2677+
body->setLastElement(func->getSingleExpressionBody());
2678+
}
26782679
// If there is a single statement in the body that can be turned into a
26792680
// single expression return, do so now.
2680-
if (auto *S = func->getBody()->getLastElement().dyn_cast<Stmt *>()) {
2681-
if (S->mayProduceSingleValue(evaluator)) {
2682-
auto *SVE = SingleValueStmtExpr::createWithWrappedBranches(
2683-
ctx, S, /*DC*/ func, /*mustBeExpr*/ false);
2684-
auto *RS = new (ctx) ReturnStmt(SourceLoc(), SVE);
2685-
body->setLastElement(RS);
2686-
func->setHasSingleExpressionBody();
2687-
func->setSingleExpressionBody(SVE);
2681+
if (!func->getResultInterfaceType()->isVoid()) {
2682+
if (auto *S = body->getSingleActiveStatement()) {
2683+
if (S->mayProduceSingleValue(evaluator)) {
2684+
auto *SVE = SingleValueStmtExpr::createWithWrappedBranches(
2685+
ctx, S, /*DC*/ func, /*mustBeExpr*/ false);
2686+
auto *RS = new (ctx) ReturnStmt(SourceLoc(), SVE);
2687+
body->setLastElement(RS);
2688+
func->setHasSingleExpressionBody();
2689+
func->setSingleExpressionBody(SVE);
2690+
}
26882691
}
26892692
}
26902693
}
@@ -2882,20 +2885,17 @@ areBranchesValidForSingleValueStmt(Evaluator &eval, ArrayRef<Stmt *> branches) {
28822885
// Check to see if there are any invalid jumps.
28832886
BS->walk(jumpFinder);
28842887

2885-
if (BS->getSingleExpressionElement()) {
2888+
if (BS->getSingleActiveExpression()) {
28862889
hadSingleExpr = true;
28872890
continue;
28882891
}
28892892

28902893
// We also allow single value statement branches, which we can wrap in
28912894
// a SingleValueStmtExpr.
2892-
auto elts = BS->getElements();
2893-
if (elts.size() == 1) {
2894-
if (auto *S = elts.back().dyn_cast<Stmt *>()) {
2895-
if (S->mayProduceSingleValue(eval)) {
2896-
hadSingleExpr = true;
2897-
continue;
2898-
}
2895+
if (auto *S = BS->getSingleActiveStatement()) {
2896+
if (S->mayProduceSingleValue(eval)) {
2897+
hadSingleExpr = true;
2898+
continue;
28992899
}
29002900
}
29012901
if (!doesBraceEndWithThrow(BS))

0 commit comments

Comments
 (0)