Merge pull request #23251 from nate-chandler/nate/omit-return

Allow return to be omitted from single expression functions.
This commit is contained in:
nate-chandler
2019-04-25 08:36:34 -07:00
committed by GitHub
34 changed files with 2163 additions and 17 deletions

View File

@@ -5671,8 +5671,60 @@ void Parser::parseAbstractFunctionBody(AbstractFunctionDecl *AFD) {
Context.Stats->getFrontendCounters().NumFunctionsParsed++;
ParserResult<BraceStmt> Body = parseBraceItemList(diag::invalid_diagnostic);
if (!Body.isNull())
AFD->setBody(Body.get());
if (!Body.isNull()) {
BraceStmt * BS = Body.get();
AFD->setBody(BS);
// If the body consists of a single expression, turn it into a return
// statement.
//
// But don't do this transformation during code completion, as the source
// may be incomplete and the type mismatch in return statement will just
// confuse the type checker.
if (!Body.hasCodeCompletion() && BS->getNumElements() == 1) {
auto Element = BS->getElement(0);
if (auto *stmt = Element.dyn_cast<Stmt *>()) {
auto kind = AFD->getKind();
if (kind == DeclKind::Var || kind == DeclKind::Subscript ||
kind == DeclKind::Func ) {
if (auto *returnStmt = dyn_cast<ReturnStmt>(stmt)) {
if (!returnStmt->hasResult()) {
auto returnExpr = TupleExpr::createEmpty(Context,
SourceLoc(),
SourceLoc(),
/*implicit*/true);
returnStmt->setResult(returnExpr);
AFD->setHasSingleExpressionBody();
AFD->setSingleExpressionBody(returnExpr);
}
}
}
} else if (auto *E = Element.dyn_cast<Expr *>()) {
if (auto SE = dyn_cast<SequenceExpr>(E->getSemanticsProvidingExpr())) {
if (SE->getNumElements() > 1 && isa<AssignExpr>(SE->getElement(1))) {
// This is an assignment. We don't want to implicitly return
// it.
return;
}
}
if (auto F = dyn_cast<FuncDecl>(AFD)) {
auto RS = new (Context) ReturnStmt(SourceLoc(), E);
BS->setElement(0, RS);
AFD->setHasSingleExpressionBody();
AFD->setSingleExpressionBody(E);
} else if (auto *F = dyn_cast<ConstructorDecl>(AFD)) {
if (F->getFailability() != OTK_None && isa<NilLiteralExpr>(E)) {
// If it's a nil literal, just insert return. This is the only
// legal thing to return.
auto RS = new (Context) ReturnStmt(E->getStartLoc(), E);
BS->setElement(0, RS);
AFD->setHasSingleExpressionBody();
AFD->setSingleExpressionBody(E);
}
}
}
}
}
}
bool Parser::parseAbstractFunctionBodyDelayed(AbstractFunctionDecl *AFD) {