Skip to content

Commit 017794a

Browse files
authored
Merge pull request #65098 from hamishknight/poundland
2 parents 3f54e99 + 3f7c3a2 commit 017794a

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
@@ -8030,8 +8030,7 @@ Parser::parseAbstractFunctionBodyImpl(AbstractFunctionDecl *AFD) {
80308030
AFD->setHasSingleExpressionBody(false);
80318031
AFD->setBodyParsed(BS, fp);
80328032

8033-
if (Parser::shouldReturnSingleExpressionElement(BS->getElements())) {
8034-
auto Element = BS->getLastElement();
8033+
if (auto Element = BS->getSingleActiveElement()) {
80358034
if (auto *stmt = Element.dyn_cast<Stmt *>()) {
80368035
if (isa<FuncDecl>(AFD)) {
80378036
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
@@ -3867,6 +3867,14 @@ class SingleValueStmtUsageChecker final : public ASTWalker {
38673867
break;
38683868
case IsSingleValueStmtResult::Kind::UnterminatedBranches: {
38693869
for (auto *branch : mayProduceSingleValue.getUnterminatedBranches()) {
3870+
if (auto *BS = dyn_cast<BraceStmt>(branch)) {
3871+
if (BS->empty()) {
3872+
Diags.diagnose(branch->getStartLoc(),
3873+
diag::single_value_stmt_branch_empty,
3874+
S->getKind());
3875+
continue;
3876+
}
3877+
}
38703878
Diags.diagnose(branch->getEndLoc(),
38713879
diag::single_value_stmt_branch_must_end_in_throw,
38723880
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
@@ -2658,23 +2658,26 @@ TypeCheckFunctionBodyRequest::evaluate(Evaluator &evaluator,
26582658

26592659
body->walk(ContextualizeClosuresAndMacros(AFD));
26602660
}
2661-
} else if (func->hasSingleExpressionBody() &&
2662-
func->getResultInterfaceType()->isVoid()) {
2663-
// The function returns void. We don't need an explicit return, no matter
2664-
// what the type of the expression is. Take the inserted return back out.
2665-
body->setLastElement(func->getSingleExpressionBody());
2666-
} else if (func->getBody()->getNumElements() == 1 &&
2667-
!func->getResultInterfaceType()->isVoid()) {
2661+
} else {
2662+
if (func->hasSingleExpressionBody() &&
2663+
func->getResultInterfaceType()->isVoid()) {
2664+
// The function returns void. We don't need an explicit return, no
2665+
// matter what the type of the expression is. Take the inserted return
2666+
// back out.
2667+
body->setLastElement(func->getSingleExpressionBody());
2668+
}
26682669
// If there is a single statement in the body that can be turned into a
26692670
// single expression return, do so now.
2670-
if (auto *S = func->getBody()->getLastElement().dyn_cast<Stmt *>()) {
2671-
if (S->mayProduceSingleValue(evaluator)) {
2672-
auto *SVE = SingleValueStmtExpr::createWithWrappedBranches(
2673-
ctx, S, /*DC*/ func, /*mustBeExpr*/ false);
2674-
auto *RS = new (ctx) ReturnStmt(SourceLoc(), SVE);
2675-
body->setLastElement(RS);
2676-
func->setHasSingleExpressionBody();
2677-
func->setSingleExpressionBody(SVE);
2671+
if (!func->getResultInterfaceType()->isVoid()) {
2672+
if (auto *S = body->getSingleActiveStatement()) {
2673+
if (S->mayProduceSingleValue(evaluator)) {
2674+
auto *SVE = SingleValueStmtExpr::createWithWrappedBranches(
2675+
ctx, S, /*DC*/ func, /*mustBeExpr*/ false);
2676+
auto *RS = new (ctx) ReturnStmt(SourceLoc(), SVE);
2677+
body->setLastElement(RS);
2678+
func->setHasSingleExpressionBody();
2679+
func->setSingleExpressionBody(SVE);
2680+
}
26782681
}
26792682
}
26802683
}
@@ -2872,20 +2875,17 @@ areBranchesValidForSingleValueStmt(Evaluator &eval, ArrayRef<Stmt *> branches) {
28722875
// Check to see if there are any invalid jumps.
28732876
BS->walk(jumpFinder);
28742877

2875-
if (BS->getSingleExpressionElement()) {
2878+
if (BS->getSingleActiveExpression()) {
28762879
hadSingleExpr = true;
28772880
continue;
28782881
}
28792882

28802883
// We also allow single value statement branches, which we can wrap in
28812884
// a SingleValueStmtExpr.
2882-
auto elts = BS->getElements();
2883-
if (elts.size() == 1) {
2884-
if (auto *S = elts.back().dyn_cast<Stmt *>()) {
2885-
if (S->mayProduceSingleValue(eval)) {
2886-
hadSingleExpr = true;
2887-
continue;
2888-
}
2885+
if (auto *S = BS->getSingleActiveStatement()) {
2886+
if (S->mayProduceSingleValue(eval)) {
2887+
hadSingleExpr = true;
2888+
continue;
28892889
}
28902890
}
28912891
if (!doesBraceEndWithThrow(BS))

0 commit comments

Comments
 (0)