Skip to content

Commit 037edf3

Browse files
committed
[SR-11711] Refactor shared parser code for single-expression returns
1 parent 3913c31 commit 037edf3

File tree

6 files changed

+90
-114
lines changed

6 files changed

+90
-114
lines changed

include/swift/Parse/Parser.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -700,6 +700,11 @@ class Parser {
700700
/// \param DiagText name for the string literal in the diagnostic.
701701
Optional<StringRef>
702702
getStringLiteralIfNotInterpolated(SourceLoc Loc, StringRef DiagText);
703+
704+
/// Returns true when body elements are eligible as single-expression implicit returns.
705+
///
706+
/// \param Body elements to search for implicit single-expression returns.
707+
bool shouldReturnSingleExpressionElement(ArrayRef<ASTNode> Body);
703708

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

lib/AST/Expr.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1974,10 +1974,10 @@ FORWARD_SOURCE_LOCS_TO(ClosureExpr, Body.getPointer())
19741974

19751975
Expr *ClosureExpr::getSingleExpressionBody() const {
19761976
assert(hasSingleExpressionBody() && "Not a single-expression body");
1977-
auto body = getBody()->getElements().back();
1977+
auto body = getBody()->getLastElement();
19781978
if (auto stmt = body.dyn_cast<Stmt *>()) {
19791979
if (auto braceStmt = dyn_cast<BraceStmt>(stmt))
1980-
return braceStmt->getElements().back().get<Expr *>();
1980+
return braceStmt->getLastElement().get<Expr *>();
19811981

19821982
return cast<ReturnStmt>(stmt)->getResult();
19831983
}
@@ -2003,7 +2003,7 @@ void AutoClosureExpr::setBody(Expr *E) {
20032003
}
20042004

20052005
Expr *AutoClosureExpr::getSingleExpressionBody() const {
2006-
return cast<ReturnStmt>(Body->getElements().back().get<Stmt *>())->getResult();
2006+
return cast<ReturnStmt>(Body->getLastElement().get<Stmt *>())->getResult();
20072007
}
20082008

20092009
Expr *AutoClosureExpr::getUnwrappedCurryThunkExpr() const {

lib/IDE/ExprContextAnalysis.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1114,13 +1114,22 @@ class ExprContextAnalyzer {
11141114
static bool isSingleExpressionBodyForCodeCompletion(BraceStmt *body) {
11151115
if (body->getNumElements() == 2) {
11161116
if (auto *D = body->getFirstElement().dyn_cast<Decl *>()) {
1117-
if (auto *ICD = dyn_cast<IfConfigDecl>(D)) {
1117+
// Step into nested active clause.
1118+
while (auto *ICD = dyn_cast<IfConfigDecl>(D)) {
11181119
auto ACE = ICD->getActiveClauseElements();
1119-
return ACE.size() == 1;
1120+
if (ACE.size() == 1) {
1121+
return body->getLastElement().is<Expr *>();
1122+
} else if (ACE.size() == 2) {
1123+
if (auto *ND = ACE.front().dyn_cast<Decl *>()) {
1124+
D = ND;
1125+
continue;
1126+
}
1127+
}
1128+
break;
11201129
}
11211130
}
11221131
}
1123-
return body->getNumElements() == 1 && body->getElements().back().is<Expr *>();
1132+
return body->getNumElements() == 1 && body->getLastElement().is<Expr *>();
11241133
}
11251134

11261135
public:

lib/Parse/ParseDecl.cpp

Lines changed: 30 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -6657,75 +6657,44 @@ BraceStmt *Parser::parseAbstractFunctionBodyImpl(AbstractFunctionDecl *AFD) {
66576657
BraceStmt *BS = Body.get();
66586658
AFD->setBodyParsed(BS);
66596659

6660-
if (BS->getNumElements() == 0)
6661-
return BS;
6662-
6663-
auto Element = BS->getFirstElement();
6664-
6665-
// If the body consists of an #if declaration with a single
6666-
// expression active clause, turn it into a return statement.
6667-
bool ReturnsLastElement = false;
6668-
if (BS->getNumElements() == 2) {
6669-
if (auto *D = Element.dyn_cast<Decl *>()) {
6670-
// Step into nested active clause.
6671-
while (auto *ICD = dyn_cast<IfConfigDecl>(D)) {
6672-
auto ACE = ICD->getActiveClauseElements();
6673-
if (ACE.size() == 1) {
6674-
Element = BS->getLastElement();
6675-
ReturnsLastElement = true;
6676-
break;
6677-
} else if (ACE.size() == 2) {
6678-
if (auto *ND = ACE.front().dyn_cast<Decl *>()) {
6679-
D = ND;
6680-
continue;
6660+
if (Parser::shouldReturnSingleExpressionElement(BS->getElements())) {
6661+
auto Element = BS->getLastElement();
6662+
if (auto *stmt = Element.dyn_cast<Stmt *>()) {
6663+
if (isa<FuncDecl>(AFD)) {
6664+
if (auto *returnStmt = dyn_cast<ReturnStmt>(stmt)) {
6665+
if (!returnStmt->hasResult()) {
6666+
auto returnExpr = TupleExpr::createEmpty(Context,
6667+
SourceLoc(),
6668+
SourceLoc(),
6669+
/*implicit*/true);
6670+
returnStmt->setResult(returnExpr);
6671+
AFD->setHasSingleExpressionBody();
6672+
AFD->setSingleExpressionBody(returnExpr);
66816673
}
66826674
}
6683-
break;
66846675
}
6685-
}
6686-
}
6687-
6688-
// If the body consists of a single expression, turn it into a return
6689-
// statement.
6690-
if (BS->getNumElements() != 1 &&
6691-
!ReturnsLastElement)
6692-
return BS;
6693-
6694-
if (auto *stmt = Element.dyn_cast<Stmt *>()) {
6695-
if (isa<FuncDecl>(AFD)) {
6696-
if (auto *returnStmt = dyn_cast<ReturnStmt>(stmt)) {
6697-
if (!returnStmt->hasResult()) {
6698-
auto returnExpr = TupleExpr::createEmpty(Context,
6699-
SourceLoc(),
6700-
SourceLoc(),
6701-
/*implicit*/true);
6702-
returnStmt->setResult(returnExpr);
6703-
AFD->setHasSingleExpressionBody();
6704-
AFD->setSingleExpressionBody(returnExpr);
6676+
} else if (auto *E = Element.dyn_cast<Expr *>()) {
6677+
if (auto SE = dyn_cast<SequenceExpr>(E->getSemanticsProvidingExpr())) {
6678+
if (SE->getNumElements() > 1 && isa<AssignExpr>(SE->getElement(1))) {
6679+
// This is an assignment. We don't want to implicitly return
6680+
// it.
6681+
return BS;
67056682
}
67066683
}
6707-
}
6708-
} else if (auto *E = Element.dyn_cast<Expr *>()) {
6709-
if (auto SE = dyn_cast<SequenceExpr>(E->getSemanticsProvidingExpr())) {
6710-
if (SE->getNumElements() > 1 && isa<AssignExpr>(SE->getElement(1))) {
6711-
// This is an assignment. We don't want to implicitly return
6712-
// it.
6713-
return BS;
6714-
}
6715-
}
6716-
if (isa<FuncDecl>(AFD)) {
6717-
auto RS = new (Context) ReturnStmt(SourceLoc(), E);
6718-
BS->getElements().back() = RS;
6719-
AFD->setHasSingleExpressionBody();
6720-
AFD->setSingleExpressionBody(E);
6721-
} else if (auto *F = dyn_cast<ConstructorDecl>(AFD)) {
6722-
if (F->isFailable() && isa<NilLiteralExpr>(E)) {
6723-
// If it's a nil literal, just insert return. This is the only
6724-
// legal thing to return.
6725-
auto RS = new (Context) ReturnStmt(E->getStartLoc(), E);
6684+
if (isa<FuncDecl>(AFD)) {
6685+
auto RS = new (Context) ReturnStmt(SourceLoc(), E);
67266686
BS->getElements().back() = RS;
67276687
AFD->setHasSingleExpressionBody();
67286688
AFD->setSingleExpressionBody(E);
6689+
} else if (auto *F = dyn_cast<ConstructorDecl>(AFD)) {
6690+
if (F->isFailable() && isa<NilLiteralExpr>(E)) {
6691+
// If it's a nil literal, just insert return. This is the only
6692+
// legal thing to return.
6693+
auto RS = new (Context) ReturnStmt(E->getStartLoc(), E);
6694+
BS->getElements().back() = RS;
6695+
AFD->setHasSingleExpressionBody();
6696+
AFD->setSingleExpressionBody(E);
6697+
}
67296698
}
67306699
}
67316700
}

lib/Parse/ParseExpr.cpp

Lines changed: 17 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -2843,56 +2843,26 @@ ParserResult<Expr> Parser::parseExprClosure() {
28432843
// If the body consists of a single expression, turn it into a return
28442844
// statement.
28452845
bool hasSingleExpressionBody = false;
2846-
if (!missingRBrace && bodyElements.size()) {
2847-
auto Element = bodyElements.front();
2846+
if (!missingRBrace &&
2847+
Parser::shouldReturnSingleExpressionElement(bodyElements)) {
2848+
auto Element = bodyElements.back();
28482849

2849-
// If the body consists of an #if declaration with a single
2850-
// expression active clause, turn it into a return statement.
2851-
bool ReturnsLastElement = false;
2852-
if (bodyElements.size() == 2) {
2853-
if (auto *D = Element.dyn_cast<Decl *>()) {
2854-
// Step into nested active clause.
2855-
while (auto *ICD = dyn_cast<IfConfigDecl>(D)) {
2856-
auto ACE = ICD->getActiveClauseElements();
2857-
if (ACE.size() == 1) {
2858-
ReturnsLastElement = true;
2859-
Element = bodyElements.back();
2860-
break;
2861-
} else if (ACE.size() == 2) {
2862-
if (auto *ND = ACE.front().dyn_cast<Decl *>()) {
2863-
D = ND;
2864-
continue;
2865-
}
2866-
}
2867-
break;
2868-
}
2869-
}
2870-
}
2871-
2872-
if (ReturnsLastElement || bodyElements.size() == 1) {
2873-
// If the closure's only body element is a single return statement,
2874-
// use that instead of creating a new wrapping return expression.
2875-
Expr *returnExpr = nullptr;
2876-
2877-
if (Element.is<Stmt *>()) {
2878-
if (auto returnStmt = dyn_cast<ReturnStmt>(Element.get<Stmt *>())) {
2879-
if (!returnStmt->hasResult()) {
2880-
returnExpr = TupleExpr::createEmpty(Context,
2881-
SourceLoc(),
2882-
SourceLoc(),
2883-
/*implicit*/true);
2884-
returnStmt->setResult(returnExpr);
2885-
}
2886-
hasSingleExpressionBody = true;
2887-
}
2888-
}
2889-
2890-
// Otherwise, create the wrapping return.
2891-
if (Element.is<Expr *>()) {
2850+
if (Element.is<Stmt *>()) {
2851+
if (auto returnStmt = dyn_cast<ReturnStmt>(Element.get<Stmt *>())) {
28922852
hasSingleExpressionBody = true;
2893-
returnExpr = Element.get<Expr*>();
2894-
bodyElements.back() = new (Context) ReturnStmt(SourceLoc(), returnExpr);
2853+
if (!returnStmt->hasResult()) {
2854+
auto returnExpr = TupleExpr::createEmpty(Context,
2855+
SourceLoc(),
2856+
SourceLoc(),
2857+
/*implicit*/true);
2858+
returnStmt->setResult(returnExpr);
2859+
}
28952860
}
2861+
} else if (Element.is<Expr *>()) {
2862+
// Create the wrapping return.
2863+
hasSingleExpressionBody = true;
2864+
auto returnExpr = Element.get<Expr*>();
2865+
bodyElements.back() = new (Context) ReturnStmt(SourceLoc(), returnExpr);
28962866
}
28972867
}
28982868

lib/Parse/Parser.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1185,6 +1185,29 @@ Parser::getStringLiteralIfNotInterpolated(SourceLoc Loc,
11851185
Segments.front().Length));
11861186
}
11871187

1188+
bool Parser::shouldReturnSingleExpressionElement(ArrayRef<ASTNode> Body) {
1189+
// If the body consists of an #if declaration with a single
1190+
// expression active clause, find a single expression.
1191+
if (Body.size() == 2) {
1192+
if (auto *D = Body.front().dyn_cast<Decl *>()) {
1193+
// Step into nested active clause.
1194+
while (auto *ICD = dyn_cast<IfConfigDecl>(D)) {
1195+
auto ACE = ICD->getActiveClauseElements();
1196+
if (ACE.size() == 1) {
1197+
return true;
1198+
} else if (ACE.size() == 2) {
1199+
if (auto *ND = ACE.front().dyn_cast<Decl *>()) {
1200+
D = ND;
1201+
continue;
1202+
}
1203+
}
1204+
break;
1205+
}
1206+
}
1207+
}
1208+
return Body.size() == 1;
1209+
}
1210+
11881211
struct ParserUnit::Implementation {
11891212
std::shared_ptr<SyntaxParseActions> SPActions;
11901213
LangOptions LangOpts;

0 commit comments

Comments
 (0)