Skip to content

Commit 8980356

Browse files
author
Nathan Hawes
committed
[Parse] Perform the single expression function body transform for delayed parsing as well
We were previously only doing it when parsing up front.
1 parent 3e0500d commit 8980356

File tree

3 files changed

+68
-66
lines changed

3 files changed

+68
-66
lines changed

include/swift/Parse/Parser.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1133,8 +1133,7 @@ class Parser {
11331133
ParseDeclOptions Flags,
11341134
DeclAttributes &Attributes,
11351135
bool HasFuncKeyword = true);
1136-
ParserResult<BraceStmt>
1137-
parseAbstractFunctionBodyImpl(AbstractFunctionDecl *AFD);
1136+
BraceStmt *parseAbstractFunctionBodyImpl(AbstractFunctionDecl *AFD);
11381137
void parseAbstractFunctionBody(AbstractFunctionDecl *AFD);
11391138
BraceStmt *parseAbstractFunctionBodyDelayed(AbstractFunctionDecl *AFD);
11401139
ParserResult<ProtocolDecl> parseDeclProtocol(ParseDeclOptions Flags,

lib/Parse/ParseDecl.cpp

Lines changed: 66 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -6442,10 +6442,9 @@ ParserResult<FuncDecl> Parser::parseDeclFunc(SourceLoc StaticLoc,
64426442
return DCC.fixupParserResult(FD);
64436443
}
64446444

6445-
/// Parse a function body for \p AFD and returns it without setting the body
6446-
/// to \p AFD .
6447-
ParserResult<BraceStmt>
6448-
Parser::parseAbstractFunctionBodyImpl(AbstractFunctionDecl *AFD) {
6445+
/// Parse a function body for \p AFD, setting the body to \p AFD before
6446+
/// returning it.
6447+
BraceStmt *Parser::parseAbstractFunctionBodyImpl(AbstractFunctionDecl *AFD) {
64496448
assert(Tok.is(tok::l_brace));
64506449

64516450
// Enter the arguments for the function into a new function-body scope. We
@@ -6473,13 +6472,70 @@ Parser::parseAbstractFunctionBodyImpl(AbstractFunctionDecl *AFD) {
64736472
CodeCompletion->completeAccessorBeginning(CCE);
64746473
RBraceLoc = Tok.getLoc();
64756474
consumeToken(tok::code_complete);
6476-
return makeParserCodeCompletionResult(
6477-
BraceStmt::create(Context, LBraceLoc, ASTNode(CCE), RBraceLoc,
6478-
/*implicit*/ true));
6475+
auto *BS = BraceStmt::create(Context, LBraceLoc, ASTNode(CCE), RBraceLoc,
6476+
/*implicit*/ true);
6477+
AFD->setBodyParsed(BS);
6478+
return BS;
64796479
}
64806480
}
64816481

6482-
return parseBraceItemList(diag::invalid_diagnostic);
6482+
ParserResult<BraceStmt> Body = parseBraceItemList(diag::invalid_diagnostic);
6483+
if (Body.isNull())
6484+
return nullptr;
6485+
6486+
BraceStmt *BS = Body.get();
6487+
AFD->setBodyParsed(BS);
6488+
6489+
// If the body consists of a single expression, turn it into a return
6490+
// statement.
6491+
//
6492+
// But don't do this transformation during code completion, as the source
6493+
// may be incomplete and the type mismatch in return statement will just
6494+
// confuse the type checker.
6495+
if (BS->getNumElements() != 1 || Body.hasCodeCompletion())
6496+
return BS;
6497+
6498+
auto Element = BS->getFirstElement();
6499+
if (auto *stmt = Element.dyn_cast<Stmt *>()) {
6500+
if (isa<FuncDecl>(AFD)) {
6501+
if (auto *returnStmt = dyn_cast<ReturnStmt>(stmt)) {
6502+
if (!returnStmt->hasResult()) {
6503+
auto returnExpr = TupleExpr::createEmpty(Context,
6504+
SourceLoc(),
6505+
SourceLoc(),
6506+
/*implicit*/true);
6507+
returnStmt->setResult(returnExpr);
6508+
AFD->setHasSingleExpressionBody();
6509+
AFD->setSingleExpressionBody(returnExpr);
6510+
}
6511+
}
6512+
}
6513+
} else if (auto *E = Element.dyn_cast<Expr *>()) {
6514+
if (auto SE = dyn_cast<SequenceExpr>(E->getSemanticsProvidingExpr())) {
6515+
if (SE->getNumElements() > 1 && isa<AssignExpr>(SE->getElement(1))) {
6516+
// This is an assignment. We don't want to implicitly return
6517+
// it.
6518+
return BS;
6519+
}
6520+
}
6521+
if (isa<FuncDecl>(AFD)) {
6522+
auto RS = new (Context) ReturnStmt(SourceLoc(), E);
6523+
BS->setFirstElement(RS);
6524+
AFD->setHasSingleExpressionBody();
6525+
AFD->setSingleExpressionBody(E);
6526+
} else if (auto *F = dyn_cast<ConstructorDecl>(AFD)) {
6527+
if (F->isFailable() && isa<NilLiteralExpr>(E)) {
6528+
// If it's a nil literal, just insert return. This is the only
6529+
// legal thing to return.
6530+
auto RS = new (Context) ReturnStmt(E->getStartLoc(), E);
6531+
BS->setFirstElement(RS);
6532+
AFD->setHasSingleExpressionBody();
6533+
AFD->setSingleExpressionBody(E);
6534+
}
6535+
}
6536+
}
6537+
6538+
return BS;
64836539
}
64846540

64856541
/// Parse function body into \p AFD or skip it for delayed parsing.
@@ -6504,60 +6560,7 @@ void Parser::parseAbstractFunctionBody(AbstractFunctionDecl *AFD) {
65046560
}
65056561

65066562
Scope S(this, ScopeKind::FunctionBody);
6507-
6508-
ParserResult<BraceStmt> Body = parseAbstractFunctionBodyImpl(AFD);
6509-
if (!Body.isNull()) {
6510-
BraceStmt * BS = Body.get();
6511-
AFD->setBodyParsed(BS);
6512-
6513-
// If the body consists of a single expression, turn it into a return
6514-
// statement.
6515-
//
6516-
// But don't do this transformation during code completion, as the source
6517-
// may be incomplete and the type mismatch in return statement will just
6518-
// confuse the type checker.
6519-
if (!Body.hasCodeCompletion() && BS->getNumElements() == 1) {
6520-
auto Element = BS->getFirstElement();
6521-
if (auto *stmt = Element.dyn_cast<Stmt *>()) {
6522-
if (isa<FuncDecl>(AFD)) {
6523-
if (auto *returnStmt = dyn_cast<ReturnStmt>(stmt)) {
6524-
if (!returnStmt->hasResult()) {
6525-
auto returnExpr = TupleExpr::createEmpty(Context,
6526-
SourceLoc(),
6527-
SourceLoc(),
6528-
/*implicit*/true);
6529-
returnStmt->setResult(returnExpr);
6530-
AFD->setHasSingleExpressionBody();
6531-
AFD->setSingleExpressionBody(returnExpr);
6532-
}
6533-
}
6534-
}
6535-
} else if (auto *E = Element.dyn_cast<Expr *>()) {
6536-
if (auto SE = dyn_cast<SequenceExpr>(E->getSemanticsProvidingExpr())) {
6537-
if (SE->getNumElements() > 1 && isa<AssignExpr>(SE->getElement(1))) {
6538-
// This is an assignment. We don't want to implicitly return
6539-
// it.
6540-
return;
6541-
}
6542-
}
6543-
if (isa<FuncDecl>(AFD)) {
6544-
auto RS = new (Context) ReturnStmt(SourceLoc(), E);
6545-
BS->setFirstElement(RS);
6546-
AFD->setHasSingleExpressionBody();
6547-
AFD->setSingleExpressionBody(E);
6548-
} else if (auto *F = dyn_cast<ConstructorDecl>(AFD)) {
6549-
if (F->isFailable() && isa<NilLiteralExpr>(E)) {
6550-
// If it's a nil literal, just insert return. This is the only
6551-
// legal thing to return.
6552-
auto RS = new (Context) ReturnStmt(E->getStartLoc(), E);
6553-
BS->setFirstElement(RS);
6554-
AFD->setHasSingleExpressionBody();
6555-
AFD->setSingleExpressionBody(E);
6556-
}
6557-
}
6558-
}
6559-
}
6560-
}
6563+
(void)parseAbstractFunctionBodyImpl(AFD);
65616564
}
65626565

65636566
BraceStmt *Parser::parseAbstractFunctionBodyDelayed(AbstractFunctionDecl *AFD) {
@@ -6589,7 +6592,7 @@ BraceStmt *Parser::parseAbstractFunctionBodyDelayed(AbstractFunctionDecl *AFD) {
65896592
Scope TopLevelScope(this, ScopeKind::TopLevel);
65906593
Scope S(this, ScopeKind::FunctionBody);
65916594

6592-
return parseAbstractFunctionBodyImpl(AFD).getPtrOrNull();
6595+
return parseAbstractFunctionBodyImpl(AFD);
65936596
}
65946597

65956598
/// Parse a 'enum' declaration, returning true (and doing no token

lib/Parse/Parser.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ void Parser::performCodeCompletionSecondPassImpl(
203203

204204
case CodeCompletionDelayedDeclKind::FunctionBody: {
205205
auto *AFD = cast<AbstractFunctionDecl>(DC);
206-
AFD->setBodyParsed(parseAbstractFunctionBodyImpl(AFD).getPtrOrNull());
206+
(void)parseAbstractFunctionBodyImpl(AFD);
207207
break;
208208
}
209209
}

0 commit comments

Comments
 (0)