Skip to content

Commit 8dc55b8

Browse files
authored
Merge pull request #67454 from hamishknight/then
2 parents 1b3d9d8 + c0ae9b9 commit 8dc55b8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+1112
-197
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,8 +1244,9 @@ ERROR(case_stmt_without_body,none,
12441244
// 'try' on statements
12451245
ERROR(try_on_stmt,none,
12461246
"'try' cannot be used with '%0'", (StringRef))
1247-
ERROR(try_on_return_throw_yield,none,
1248-
"'try' must be placed on the %select{returned|thrown|yielded}0 expression",
1247+
ERROR(try_must_come_after_stmt,none,
1248+
"'try' must be placed on the %select{returned|thrown|yielded|produced}0 "
1249+
"expression",
12491250
(unsigned))
12501251
ERROR(try_on_var_let,none,
12511252
"'try' must be placed on the initial value expression", ())
@@ -1399,6 +1400,12 @@ ERROR(expected_expr_after_each, none,
13991400
"expected expression after 'each'", ())
14001401
ERROR(expected_expr_after_repeat, none,
14011402
"expected expression after 'repeat'", ())
1403+
ERROR(expected_expr_after_then,none,
1404+
"expected expression after 'then'", ())
1405+
1406+
WARNING(unindented_code_after_then,none,
1407+
"expression following 'then' is treated as an argument of "
1408+
"the 'then'", ())
14021409

14031410
WARNING(move_consume_final_spelling, none,
14041411
"'_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
@@ -1231,14 +1231,18 @@ ERROR(if_expr_must_be_syntactically_exhaustive,none,
12311231
ERROR(single_value_stmt_branch_empty,none,
12321232
"expected expression in branch of '%0' expression",
12331233
(StmtKind))
1234-
ERROR(single_value_stmt_branch_must_end_in_throw,none,
1235-
"non-expression branch of '%0' expression may only end with a 'throw'",
1234+
ERROR(single_value_stmt_branch_must_end_in_result,none,
1235+
"non-expression branch of '%0' expression may only end with a 'throw' "
1236+
"or 'then'",
12361237
(StmtKind))
12371238
ERROR(cannot_jump_in_single_value_stmt,none,
12381239
"cannot '%0' in '%1' when used as expression",
12391240
(StmtKind, StmtKind))
12401241
ERROR(effect_marker_on_single_value_stmt,none,
12411242
"'%0' may not be used on '%1' expression", (StringRef, StmtKind))
1243+
ERROR(out_of_place_then_stmt,none,
1244+
"'then' may only appear as the last statement in an 'if' or 'switch' "
1245+
"expression", ())
12421246

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

include/swift/AST/Expr.h

Lines changed: 20 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.
@@ -6144,6 +6145,16 @@ class SingleValueStmtExpr : public Expr {
61446145
/// SingleValueStmtExpr.
61456146
static SingleValueStmtExpr *tryDigOutSingleValueStmtExpr(Expr *E);
61466147

6148+
/// Retrieves a resulting ThenStmt from the given BraceStmt, or \c nullptr if
6149+
/// the brace does not have a resulting ThenStmt.
6150+
static ThenStmt *getThenStmtFrom(BraceStmt *BS);
6151+
6152+
/// Whether the given BraceStmt has a result to be produced from a parent
6153+
/// SingleValueStmtExpr.
6154+
static bool hasResult(BraceStmt *BS) {
6155+
return getThenStmtFrom(BS);
6156+
}
6157+
61476158
/// Retrieve the wrapped statement.
61486159
Stmt *getStmt() const { return S; }
61496160
void setStmt(Stmt *newS) { S = newS; }
@@ -6154,10 +6165,15 @@ class SingleValueStmtExpr : public Expr {
61546165
/// Retrieve the complete set of branches for the underlying statement.
61556166
ArrayRef<Stmt *> getBranches(SmallVectorImpl<Stmt *> &scratch) const;
61566167

6157-
/// Retrieve the single expression branches of the statement, excluding
6158-
/// branches that either have multiple expressions, or have statements.
6168+
/// Retrieve the resulting ThenStmts from each branch of the
6169+
/// SingleValueStmtExpr.
6170+
ArrayRef<ThenStmt *>
6171+
getThenStmts(SmallVectorImpl<ThenStmt *> &scratch) const;
6172+
6173+
/// Retrieve the result expressions from each branch of the
6174+
/// SingleValueStmtExpr.
61596175
ArrayRef<Expr *>
6160-
getSingleExprBranches(SmallVectorImpl<Expr *> &scratch) const;
6176+
getResultExprs(SmallVectorImpl<Expr *> &scratch) const;
61616177

61626178
DeclContext *getDeclContext() const { return DC; }
61636179

include/swift/AST/NameLookup.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,7 @@ class FindLocalVal : public StmtVisitor<FindLocalVal> {
667667
void visitFailStmt(FailStmt *) {}
668668
void visitReturnStmt(ReturnStmt *) {}
669669
void visitYieldStmt(YieldStmt *) {}
670+
void visitThenStmt(ThenStmt *) {}
670671
void visitThrowStmt(ThrowStmt *) {}
671672
void visitDiscardStmt(DiscardStmt *) {}
672673
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/TokenKinds.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ MISC(string_segment)
258258
MISC(string_interpolation_anchor)
259259
MISC(kw_yield)
260260
MISC(kw_discard)
261+
MISC(kw_then)
261262

262263
// The following tokens are irrelevant for swiftSyntax and thus only declared
263264
// in this .def file

include/swift/AST/TypeCheckRequests.h

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

3904-
/// There are no single-expression branches.
3905-
NoExpressionBranches,
3904+
/// There is no branch that produces a resulting value.
3905+
NoResult,
39063906

39073907
/// There is an unhandled statement branch. This should only be the case
39083908
/// for invalid AST.
@@ -3957,8 +3957,8 @@ class IsSingleValueStmtResult {
39573957
static IsSingleValueStmtResult nonExhaustiveIf() {
39583958
return IsSingleValueStmtResult(Kind::NonExhaustiveIf);
39593959
}
3960-
static IsSingleValueStmtResult noExpressionBranches() {
3961-
return IsSingleValueStmtResult(Kind::NoExpressionBranches);
3960+
static IsSingleValueStmtResult noResult() {
3961+
return IsSingleValueStmtResult(Kind::NoResult);
39623962
}
39633963
static IsSingleValueStmtResult unhandledStmt() {
39643964
return IsSingleValueStmtResult(Kind::UnhandledStmt);

include/swift/Basic/Features.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,9 @@ EXPERIMENTAL_FEATURE(GlobalConcurrency, false)
226226
/// "playground transform" is enabled.
227227
EXPERIMENTAL_FEATURE(PlaygroundExtendedCallbacks, true)
228228

229+
/// Enable 'then' statements.
230+
EXPERIMENTAL_FEATURE(ThenStatements, false)
231+
229232
/// Enable the `@_rawLayout` attribute.
230233
EXPERIMENTAL_FEATURE(RawLayout, true)
231234

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

0 commit comments

Comments
 (0)