Skip to content

Commit bb194a9

Browse files
committed
xxx
1 parent 90d62e8 commit bb194a9

39 files changed

+576
-154
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,8 +1248,9 @@ ERROR(case_stmt_without_body,none,
12481248
// 'try' on statements
12491249
ERROR(try_on_stmt,none,
12501250
"'try' cannot be used with '%0'", (StringRef))
1251-
ERROR(try_on_return_throw_yield,none,
1252-
"'try' must be placed on the %select{returned|thrown|yielded}0 expression",
1251+
ERROR(try_must_come_after_stmt,none,
1252+
"'try' must be placed on the %select{returned|thrown|yielded|produced}0 "
1253+
"expression",
12531254
(unsigned))
12541255
ERROR(try_on_var_let,none,
12551256
"'try' must be placed on the initial value expression", ())
@@ -1403,6 +1404,8 @@ ERROR(expected_expr_after_each, none,
14031404
"expected expression after 'each'", ())
14041405
ERROR(expected_expr_after_repeat, none,
14051406
"expected expression after 'repeat'", ())
1407+
ERROR(expected_expr_after_then, none,
1408+
"expected expression after 'then'", ())
14061409

14071410
WARNING(move_consume_final_spelling, none,
14081411
"'_move' has been renamed to 'consume', and the '_move' spelling will be removed shortly", ())

include/swift/AST/DiagnosticsSema.def

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1225,14 +1225,18 @@ ERROR(if_expr_must_be_syntactically_exhaustive,none,
12251225
ERROR(single_value_stmt_branch_empty,none,
12261226
"expected expression in branch of '%0' expression",
12271227
(StmtKind))
1228-
ERROR(single_value_stmt_branch_must_end_in_throw,none,
1229-
"non-expression branch of '%0' expression may only end with a 'throw'",
1228+
ERROR(single_value_stmt_branch_must_end_in_result,none,
1229+
"non-expression branch of '%0' expression may only end with a 'throw' "
1230+
"or 'then'",
12301231
(StmtKind))
12311232
ERROR(cannot_jump_in_single_value_stmt,none,
12321233
"cannot '%0' in '%1' when used as expression",
12331234
(StmtKind, StmtKind))
12341235
ERROR(effect_marker_on_single_value_stmt,none,
12351236
"'%0' may not be used on '%1' expression", (StringRef, StmtKind))
1237+
ERROR(out_of_place_then_stmt,none,
1238+
"'then' may only appear as the last statement in an 'if' or 'switch' "
1239+
"expression", ())
12361240

12371241
ERROR(did_not_call_function_value,none,
12381242
"function value was used as a property; add () to call it",

include/swift/AST/Expr.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ namespace swift {
7070
class CallExpr;
7171
class KeyPathExpr;
7272
class CaptureListExpr;
73+
class ThenStmt;
7374

7475
enum class ExprKind : uint8_t {
7576
#define EXPR(Id, Parent) Id,
@@ -6125,10 +6126,10 @@ class SingleValueStmtExpr : public Expr {
61256126
SingleValueStmtExpr(Stmt *S, DeclContext *DC)
61266127
: Expr(ExprKind::SingleValueStmt, /*isImplicit*/ true), S(S), DC(DC) {}
61276128

6128-
public:
61296129
/// Creates a new SingleValueStmtExpr wrapping a statement.
61306130
static SingleValueStmtExpr *create(ASTContext &ctx, Stmt *S, DeclContext *DC);
61316131

6132+
public:
61326133
/// Creates a new SingleValueStmtExpr wrapping a statement, and recursively
61336134
/// attempts to wrap any branches of that statement that can become single
61346135
/// value statement expressions.
@@ -6154,10 +6155,13 @@ class SingleValueStmtExpr : public Expr {
61546155
/// Retrieve the complete set of branches for the underlying statement.
61556156
ArrayRef<Stmt *> getBranches(SmallVectorImpl<Stmt *> &scratch) const;
61566157

6157-
/// Retrieve the single expression branches of the statement, excluding
6158-
/// branches that either have multiple expressions, or have statements.
6158+
/// Retrieve the result stmts from each branch of the SingleValueStmtExpr.
6159+
ArrayRef<ThenStmt *>
6160+
getResultStmts(SmallVectorImpl<ThenStmt *> &scratch) const;
6161+
6162+
/// Retrieve the result exprs from each branch of the SingleValueStmtExpr.
61596163
ArrayRef<Expr *>
6160-
getSingleExprBranches(SmallVectorImpl<Expr *> &scratch) const;
6164+
getResultExprs(SmallVectorImpl<Expr *> &scratch) const;
61616165

61626166
DeclContext *getDeclContext() const { return DC; }
61636167

include/swift/AST/NameLookup.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,7 @@ class FindLocalVal : public StmtVisitor<FindLocalVal> {
665665
void visitFailStmt(FailStmt *) {}
666666
void visitReturnStmt(ReturnStmt *) {}
667667
void visitYieldStmt(YieldStmt *) {}
668+
void visitThenStmt(ThenStmt *) {}
668669
void visitThrowStmt(ThrowStmt *) {}
669670
void visitDiscardStmt(DiscardStmt *) {}
670671
void visitPoundAssertStmt(PoundAssertStmt *) {}

include/swift/AST/Stmt.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,38 @@ class YieldStmt final
304304
static bool classof(const Stmt *S) { return S->getKind() == StmtKind::Yield; }
305305
};
306306

307+
/// The statement `then <expr>`. This is used within if/switch expressions to
308+
/// indicate the value being produced by a given branch.
309+
class ThenStmt : public Stmt {
310+
SourceLoc ThenLoc;
311+
Expr *Result;
312+
313+
ThenStmt(SourceLoc thenLoc, Expr *result, bool isImplicit)
314+
: Stmt(StmtKind::Then, isImplicit), ThenLoc(thenLoc), Result(result) {
315+
assert(Result && "Must have non-null result");
316+
}
317+
318+
public:
319+
/// Create a new parsed ThenStmt.
320+
static ThenStmt *createParsed(ASTContext &ctx, SourceLoc thenLoc,
321+
Expr *result);
322+
323+
/// Create an implicit ThenStmt.
324+
///
325+
/// Note that such statements will be elided during the result builder
326+
/// transform.
327+
static ThenStmt *createImplicit(ASTContext &ctx, Expr *result);
328+
329+
SourceLoc getThenLoc() const { return ThenLoc; }
330+
331+
SourceRange getSourceRange() const;
332+
333+
Expr *getResult() const { return Result; }
334+
void setResult(Expr *e) { Result = e; }
335+
336+
static bool classof(const Stmt *S) { return S->getKind() == StmtKind::Then; }
337+
};
338+
307339
/// DeferStmt - A 'defer' statement. This runs the substatement it contains
308340
/// when the enclosing scope is exited.
309341
///

include/swift/AST/StmtNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646

4747
STMT(Brace, Stmt)
4848
STMT(Return, Stmt)
49+
STMT(Then, Stmt)
4950
STMT(Yield, Stmt)
5051
STMT(Defer, Stmt)
5152
ABSTRACT_STMT(Labeled, Stmt)

include/swift/AST/TypeCheckRequests.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3859,8 +3859,8 @@ class IsSingleValueStmtResult {
38593859
/// The statement is an 'if' statement without an unconditional 'else'.
38603860
NonExhaustiveIf,
38613861

3862-
/// There are no single-expression branches.
3863-
NoExpressionBranches,
3862+
/// There are no branch that produces a resulting value.
3863+
NoResult,
38643864

38653865
/// There is an unhandled statement branch. This should only be the case
38663866
/// for invalid AST.
@@ -3915,8 +3915,8 @@ class IsSingleValueStmtResult {
39153915
static IsSingleValueStmtResult nonExhaustiveIf() {
39163916
return IsSingleValueStmtResult(Kind::NonExhaustiveIf);
39173917
}
3918-
static IsSingleValueStmtResult noExpressionBranches() {
3919-
return IsSingleValueStmtResult(Kind::NoExpressionBranches);
3918+
static IsSingleValueStmtResult noResult() {
3919+
return IsSingleValueStmtResult(Kind::NoResult);
39203920
}
39213921
static IsSingleValueStmtResult unhandledStmt() {
39223922
return IsSingleValueStmtResult(Kind::UnhandledStmt);

include/swift/IDE/CodeCompletionResult.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ enum class CompletionKind : uint8_t {
213213
CallArg,
214214
LabeledTrailingClosure,
215215
ReturnStmtExpr,
216+
ThenStmtExpr,
216217
YieldStmtExpr,
217218
ForEachSequence,
218219

include/swift/Parse/IDEInspectionCallbacks.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,8 @@ class CodeCompletionCallbacks {
235235

236236
virtual void completeReturnStmt(CodeCompletionExpr *E) {};
237237

238+
virtual void completeThenStmt(CodeCompletionExpr *E) {};
239+
238240
/// Complete a yield statement. A missing yield index means that the
239241
/// completion immediately follows the 'yield' keyword; it may be either
240242
/// an expression or a parenthesized expression list. A present yield

include/swift/Parse/Parser.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,10 @@ class Parser {
602602
cast<AccessorDecl>(CurDeclContext)->isCoroutine());
603603
}
604604

605+
/// Whether the current token is the contextual keyword for a \c then
606+
/// statement.
607+
bool isContextualThenKeyword();
608+
605609
/// `discard self` is the only valid phrase, but we peek ahead for just any
606610
/// identifier after `discard` to determine if it's the statement. This helps
607611
/// us avoid interpreting `discard(self)` as the statement and not a call.
@@ -1933,6 +1937,7 @@ class Parser {
19331937
ParserResult<Stmt> parseStmtContinue();
19341938
ParserResult<Stmt> parseStmtReturn(SourceLoc tryLoc);
19351939
ParserResult<Stmt> parseStmtYield(SourceLoc tryLoc);
1940+
ParserResult<Stmt> parseStmtThen(SourceLoc tryLoc);
19361941
ParserResult<Stmt> parseStmtThrow(SourceLoc tryLoc);
19371942
ParserResult<Stmt> parseStmtDiscard();
19381943
ParserResult<Stmt> parseStmtDefer();

include/swift/Sema/ConstraintLocator.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -931,19 +931,19 @@ class LocatorPathElt::TernaryBranch final : public StoredIntegerElement<1> {
931931
}
932932
};
933933

934-
/// The branch of a SingleValueStmtExpr. Note the stored index corresponds to
935-
/// the expression branches, i.e it skips statement branch indices.
936-
class LocatorPathElt::SingleValueStmtBranch final
934+
/// A particular result of a ThenStmt at a given index in a SingleValueStmtExpr.
935+
/// The stored index corresponds to the \c getResultExprs array.
936+
class LocatorPathElt::SingleValueStmtResult final
937937
: public StoredIntegerElement<1> {
938938
public:
939-
SingleValueStmtBranch(unsigned exprIdx)
940-
: StoredIntegerElement(ConstraintLocator::SingleValueStmtBranch,
939+
SingleValueStmtResult(unsigned exprIdx)
940+
: StoredIntegerElement(ConstraintLocator::SingleValueStmtResult,
941941
exprIdx) {}
942942

943-
unsigned getExprBranchIndex() const { return getValue(); }
943+
unsigned getIndex() const { return getValue(); }
944944

945945
static bool classof(const LocatorPathElt *elt) {
946-
return elt->getKind() == ConstraintLocator::SingleValueStmtBranch;
946+
return elt->getKind() == ConstraintLocator::SingleValueStmtResult;
947947
}
948948
};
949949

include/swift/Sema/ConstraintLocatorPathElts.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,8 +259,8 @@ CUSTOM_LOCATOR_PATH_ELT(SyntacticElement)
259259
/// The element of the pattern binding declaration.
260260
CUSTOM_LOCATOR_PATH_ELT(PatternBindingElement)
261261

262-
/// A branch of a SingleValueStmtExpr.
263-
CUSTOM_LOCATOR_PATH_ELT(SingleValueStmtBranch)
262+
/// A particular result of a ThenStmt at a given index in a SingleValueStmtExpr.
263+
CUSTOM_LOCATOR_PATH_ELT(SingleValueStmtResult)
264264

265265
/// A declaration introduced by a pattern: name (i.e. `x`) or `_`
266266
ABSTRACT_LOCATOR_PATH_ELT(PatternDecl)

lib/AST/ASTDumper.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1640,6 +1640,13 @@ class PrintStmt : public StmtVisitor<PrintStmt> {
16401640
PrintWithColorRAII(OS, ParenthesisColor) << ')';
16411641
}
16421642

1643+
void visitThenStmt(ThenStmt *S) {
1644+
printCommon(S, "then_stmt");
1645+
OS << '\n';
1646+
printRec(S->getResult());
1647+
PrintWithColorRAII(OS, ParenthesisColor) << ')';
1648+
}
1649+
16431650
void visitDeferStmt(DeferStmt *S) {
16441651
printCommon(S, "defer_stmt") << '\n';
16451652
printRec(S->getTempDecl());

lib/AST/ASTPrinter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5496,6 +5496,11 @@ void PrintAST::visitYieldStmt(YieldStmt *stmt) {
54965496
if (parens) Printer << ")";
54975497
}
54985498

5499+
void PrintAST::visitThenStmt(ThenStmt *stmt) {
5500+
Printer.printKeyword("then", Options, " ");
5501+
visit(stmt->getResult());
5502+
}
5503+
54995504
void PrintAST::visitThrowStmt(ThrowStmt *stmt) {
55005505
Printer << tok::kw_throw << " ";
55015506
visit(stmt->getSubExpr());

lib/AST/ASTScopeCreation.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,12 @@ class NodeAdder
437437
return p;
438438
}
439439

440+
ASTScopeImpl *visitThenStmt(ThenStmt *ts, ASTScopeImpl *p,
441+
ScopeCreator &scopeCreator) {
442+
visitExpr(ts->getResult(), p, scopeCreator);
443+
return p;
444+
}
445+
440446
ASTScopeImpl *visitDeferStmt(DeferStmt *ds, ASTScopeImpl *p,
441447
ScopeCreator &scopeCreator) {
442448
visitFuncDecl(ds->getTempDecl(), p, scopeCreator);

lib/AST/ASTVerifier.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1214,7 +1214,7 @@ class Verifier : public ASTWalker {
12141214
void verifyChecked(SingleValueStmtExpr *E) {
12151215
using Kind = IsSingleValueStmtResult::Kind;
12161216
switch (E->getStmt()->mayProduceSingleValue(Ctx).getKind()) {
1217-
case Kind::NoExpressionBranches:
1217+
case Kind::NoResult:
12181218
// These are allowed as long as the type is Void.
12191219
checkSameType(
12201220
E->getType(), Ctx.getVoidType(),

lib/AST/ASTWalker.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1758,6 +1758,15 @@ Stmt *Traversal::visitYieldStmt(YieldStmt *YS) {
17581758
return YS;
17591759
}
17601760

1761+
Stmt *Traversal::visitThenStmt(ThenStmt *TS) {
1762+
auto *E = doIt(TS->getResult());
1763+
if (!E)
1764+
return nullptr;
1765+
1766+
TS->setResult(E);
1767+
return TS;
1768+
}
1769+
17611770
Stmt *Traversal::visitDeferStmt(DeferStmt *DS) {
17621771
if (doIt(DS->getTempDecl()))
17631772
return nullptr;

lib/AST/Expr.cpp

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2492,27 +2492,29 @@ SingleValueStmtExpr *SingleValueStmtExpr::createWithWrappedBranches(
24922492
if (!BS)
24932493
continue;
24942494

2495-
auto *S = BS->getSingleActiveStatement();
2496-
if (!S)
2497-
continue;
2498-
2499-
if (mustBeExpr) {
2500-
// If this must be an expression, we can eagerly wrap any exhaustive if
2501-
// and switch branch.
2502-
if (auto *IS = dyn_cast<IfStmt>(S)) {
2503-
if (!IS->isSyntacticallyExhaustive())
2495+
if (auto *S = BS->getSingleActiveStatement()) {
2496+
if (mustBeExpr) {
2497+
// If this must be an expression, we can eagerly wrap any exhaustive if
2498+
// and switch branch.
2499+
if (auto *IS = dyn_cast<IfStmt>(S)) {
2500+
if (!IS->isSyntacticallyExhaustive())
2501+
continue;
2502+
} else if (!isa<SwitchStmt>(S)) {
2503+
continue;
2504+
}
2505+
} else {
2506+
// Otherwise do the semantic checking to verify that we can wrap the
2507+
// branch.
2508+
if (!S->mayProduceSingleValue(ctx))
25042509
continue;
2505-
} else if (!isa<SwitchStmt>(S)) {
2506-
continue;
25072510
}
2508-
} else {
2509-
// Otherwise do the semantic checking to verify that we can wrap the
2510-
// branch.
2511-
if (!S->mayProduceSingleValue(ctx))
2512-
continue;
2511+
BS->setLastElement(SingleValueStmtExpr::createWithWrappedBranches(
2512+
ctx, S, DC, mustBeExpr));
25132513
}
2514-
BS->setLastElement(
2515-
SingleValueStmtExpr::createWithWrappedBranches(ctx, S, DC, mustBeExpr));
2514+
2515+
// Wrap single expression branches in an implicit 'then <expr>'.
2516+
if (auto *E = BS->getSingleActiveExpression())
2517+
BS->setLastElement(ThenStmt::createImplicit(ctx, E));
25162518
}
25172519
return SVE;
25182520
}
@@ -2571,20 +2573,31 @@ SingleValueStmtExpr::getBranches(SmallVectorImpl<Stmt *> &scratch) const {
25712573
llvm_unreachable("Unhandled case in switch!");
25722574
}
25732575

2574-
ArrayRef<Expr *> SingleValueStmtExpr::getSingleExprBranches(
2575-
SmallVectorImpl<Expr *> &scratch) const {
2576+
ArrayRef<ThenStmt *> SingleValueStmtExpr::getResultStmts(
2577+
SmallVectorImpl<ThenStmt *> &scratch) const {
25762578
assert(scratch.empty());
25772579
SmallVector<Stmt *, 4> stmtScratch;
25782580
for (auto *branch : getBranches(stmtScratch)) {
25792581
auto *BS = dyn_cast<BraceStmt>(branch);
2580-
if (!BS)
2582+
if (!BS || BS->empty())
25812583
continue;
2582-
if (auto *E = BS->getSingleActiveExpression())
2583-
scratch.push_back(E);
2584+
if (auto *S = BS->getLastElement().dyn_cast<Stmt *>()) {
2585+
if (auto *TS = dyn_cast<ThenStmt>(S))
2586+
scratch.push_back(TS);
2587+
}
25842588
}
25852589
return scratch;
25862590
}
25872591

2592+
ArrayRef<Expr *> SingleValueStmtExpr::getResultExprs(
2593+
SmallVectorImpl<Expr *> &scratch) const {
2594+
SmallVector<ThenStmt *, 4> stmtScratch;
2595+
for (auto *TS : getResultStmts(stmtScratch))
2596+
scratch.push_back(TS->getResult());
2597+
2598+
return scratch;
2599+
}
2600+
25882601
void InterpolatedStringLiteralExpr::forEachSegment(ASTContext &Ctx,
25892602
llvm::function_ref<void(bool, CallExpr *)> callback) {
25902603
auto appendingExpr = getAppendingExpr();

0 commit comments

Comments
 (0)