Skip to content

Commit 1e40f0c

Browse files
committed
xxx
1 parent 0d87cd3 commit 1e40f0c

Some content is hidden

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

68 files changed

+3512
-155
lines changed

include/swift/AST/ASTScope.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -955,6 +955,7 @@ class PatternEntryInitializerScope final : public AbstractPatternEntryScope {
955955

956956
protected:
957957
bool lookupLocalsOrMembers(DeclConsumer) const override;
958+
bool isLabeledStmtLookupTerminator() const override;
958959
};
959960

960961
/// The scope introduced by a conditional clause initializer in an

include/swift/AST/ASTTypeIDZone.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ SWIFT_TYPEID(Fingerprint)
2626
SWIFT_TYPEID(GenericSignature)
2727
SWIFT_TYPEID(ImplicitImportList)
2828
SWIFT_TYPEID(ImplicitMemberAction)
29+
SWIFT_TYPEID(IsSingleValueStmtResult)
2930
SWIFT_TYPEID(ParamSpecifier)
3031
SWIFT_TYPEID(PropertyWrapperAuxiliaryVariables)
3132
SWIFT_TYPEID(PropertyWrapperInitializerInfo)

include/swift/AST/ASTTypeIDs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ class GenericParamList;
4141
class GenericSignature;
4242
class GenericTypeParamType;
4343
class InfixOperatorDecl;
44+
class IsSingleValueStmtResult;
4445
class IterableDeclContext;
4546
class ModuleDecl;
4647
struct ImplicitImportList;

include/swift/AST/DiagnosticsSema.def

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,6 +1080,31 @@ ERROR(ternary_expr_cases_mismatch,none,
10801080
"result values in '? :' expression have mismatching types %0 and %1",
10811081
(Type, Type))
10821082

1083+
ERROR(single_value_stmt_branches_mismatch,none,
1084+
"branches have mismatching types %0 and %1",
1085+
(Type, Type))
1086+
1087+
ERROR(single_value_stmt_out_of_place,none,
1088+
"'%0' may only be used as expression in return, throw, coercion, or as "
1089+
"the source of an assignment",
1090+
(StmtKind))
1091+
1092+
ERROR(single_value_stmt_must_be_unlabeled,none,
1093+
"'%0' cannot have a jump label when used as expression",
1094+
(StmtKind))
1095+
1096+
ERROR(if_expr_must_be_syntactically_exhaustive,none,
1097+
"'if' must have an unconditional 'else' to be used as expression",
1098+
())
1099+
1100+
ERROR(single_value_stmt_branch_must_return_or_throw,none,
1101+
"non-expression branch of '%0' expression must end in "
1102+
"'return' or 'throw'", (StmtKind))
1103+
1104+
ERROR(cannot_jump_in_single_value_stmt,none,
1105+
"cannot '%0' in '%1' when used as expression",
1106+
(StmtKind, StmtKind))
1107+
10831108
ERROR(did_not_call_function_value,none,
10841109
"function value was used as a property; add () to call it",
10851110
())
@@ -4353,6 +4378,10 @@ WARNING(trailing_closure_requires_parens,none,
43534378
" statement; pass as a parenthesized argument to silence this warning",
43544379
())
43554380

4381+
// Statements as expressions
4382+
ERROR(non_single_value_stmt_as_expr,none,
4383+
"expected single expression branches for expression statement", ())
4384+
43564385
ERROR(opaque_type_no_underlying_type_candidates,none,
43574386
"function declares an opaque return type, but has no return statements "
43584387
"in its body from which to infer an underlying type", ())

include/swift/AST/Expr.h

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5935,6 +5935,55 @@ class KeyPathDotExpr : public Expr {
59355935
}
59365936
};
59375937

5938+
/// An expression that may wrap a statement which produces a single value.
5939+
class SingleValueStmtExpr : public Expr {
5940+
public:
5941+
enum class Kind {
5942+
If, Switch
5943+
};
5944+
5945+
private:
5946+
Stmt *S;
5947+
DeclContext *DC;
5948+
5949+
SingleValueStmtExpr(Stmt *S, DeclContext *DC)
5950+
: Expr(ExprKind::SingleValueStmt, /*isImplicit*/ true), S(S), DC(DC) {}
5951+
5952+
public:
5953+
/// Creates a new SingleValueStmtExpr wrapping a statement.
5954+
static SingleValueStmtExpr *create(ASTContext &ctx, Stmt *S, DeclContext *DC);
5955+
5956+
/// Creates a new SingleValueStmtExpr wrapping a statement, and recursively
5957+
/// attempts to wrap any branches of that statement that can become a single
5958+
/// value statement expression. If \p forParse is true, branches will be
5959+
/// eagerly wrapped even if they may not be valid SingleValueStmtExprs.
5960+
static SingleValueStmtExpr *createWithWrappedBranches(ASTContext &ctx, Stmt *S,
5961+
DeclContext *DC,
5962+
bool forParse);
5963+
/// Retrieve the wrapped statement.
5964+
Stmt *getStmt() const { return S; }
5965+
void setStmt(Stmt *newS) { S = newS; }
5966+
5967+
/// Retrieve the kind of statement being wrapped.
5968+
Kind getStmtKind() const;
5969+
5970+
/// Retrieve the complete set of branches for the underlying statement.
5971+
ArrayRef<Stmt *> getBranches(SmallVectorImpl<Stmt *> &scratch) const;
5972+
5973+
/// Retrieve the single expression branches of the statement, excluding
5974+
/// branches that either have multiple expressions, or have statements.
5975+
ArrayRef<Expr *>
5976+
getSingleExprBranches(SmallVectorImpl<Expr *> &scratch) const;
5977+
5978+
DeclContext *getDeclContext() const { return DC; }
5979+
5980+
SourceRange getSourceRange() const;
5981+
5982+
static bool classof(const Expr *E) {
5983+
return E->getKind() == ExprKind::SingleValueStmt;
5984+
}
5985+
};
5986+
59385987
/// Expression node that effects a "one-way" constraint in
59395988
/// the constraint system, allowing type information to flow from the
59405989
/// subexpression outward but not the other way.

include/swift/AST/ExprNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ EXPR(LazyInitializer, Expr)
203203
EXPR(EditorPlaceholder, Expr)
204204
EXPR(ObjCSelector, Expr)
205205
EXPR(KeyPath, Expr)
206+
EXPR(SingleValueStmt, Expr)
206207
UNCHECKED_EXPR(KeyPathDot, Expr)
207208
UNCHECKED_EXPR(OneWay, Expr)
208209
EXPR(Tap, Expr)

include/swift/AST/Stmt.h

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,15 @@ class ASTContext;
3535
class ASTWalker;
3636
class Decl;
3737
class DeclContext;
38+
class Evaluator;
3839
class Expr;
3940
class FuncDecl;
4041
class Pattern;
4142
class PatternBindingDecl;
4243
class VarDecl;
4344
class CaseStmt;
4445
class DoCatchStmt;
46+
class IsSingleValueStmtResult;
4547
class SwitchStmt;
4648

4749
enum class StmtKind {
@@ -133,7 +135,12 @@ class alignas(8) Stmt : public ASTAllocated<Stmt> {
133135

134136
SourceRange getSourceRange() const;
135137
SourceLoc TrailingSemiLoc;
136-
138+
139+
/// Whether the statement can produce a single value, and as such may be
140+
/// treated as an expression.
141+
IsSingleValueStmtResult mayProduceSingleValue(Evaluator &eval) const;
142+
IsSingleValueStmtResult mayProduceSingleValue(ASTContext &ctx) const;
143+
137144
/// isImplicit - Determines whether this statement was implicitly-generated,
138145
/// rather than explicitly written in the AST.
139146
bool isImplicit() const { return Bits.Stmt.Implicit; }
@@ -204,6 +211,8 @@ class BraceStmt final : public Stmt,
204211

205212
ASTNode findAsyncNode();
206213

214+
Expr *getSingleExpressionBody() const;
215+
207216
static bool classof(const Stmt *S) { return S->getKind() == StmtKind::Brace; }
208217
};
209218

@@ -711,7 +720,14 @@ class IfStmt : public LabeledConditionalStmt {
711720

712721
Stmt *getElseStmt() const { return Else; }
713722
void setElseStmt(Stmt *s) { Else = s; }
714-
723+
724+
/// Retrieve the complete set of branches for this if statement, including
725+
/// else if statements.
726+
ArrayRef<Stmt *> getBranches(SmallVectorImpl<Stmt *> &scratch) const;
727+
728+
/// Whether the if statement has an unconditional \c else.
729+
bool isSyntacticallyExhaustive() const;
730+
715731
// Implement isa/cast/dyncast/etc.
716732
static bool classof(const Stmt *S) { return S->getKind() == StmtKind::If; }
717733
};
@@ -1283,7 +1299,10 @@ class SwitchStmt final : public LabeledStmt,
12831299
AsCaseStmtRange getCases() const {
12841300
return AsCaseStmtRange(getRawCases(), AsCaseStmtWithSkippingNonCaseStmts());
12851301
}
1286-
1302+
1303+
/// Retrieve the complete set of branches for this switch statement.
1304+
ArrayRef<Stmt *> getBranches(SmallVectorImpl<Stmt *> &scratch) const;
1305+
12871306
static bool classof(const Stmt *S) {
12881307
return S->getKind() == StmtKind::Switch;
12891308
}

include/swift/AST/TypeCheckRequests.h

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3752,6 +3752,100 @@ class GetTypeWrapperInitializer
37523752
bool isCached() const { return true; }
37533753
};
37543754

3755+
/// The result of the query for whether a statement can produce a single value.
3756+
class IsSingleValueStmtResult {
3757+
public:
3758+
enum class Kind {
3759+
Valid,
3760+
UnterminatedBranch,
3761+
NonExhaustiveIf,
3762+
NoExpressionBranches,
3763+
UnhandledStmt,
3764+
CircularReference,
3765+
InvalidJumps,
3766+
HasLabel
3767+
};
3768+
3769+
private:
3770+
Kind TheKind;
3771+
Stmt *UnterminatedBranch;
3772+
std::vector<Stmt *> InvalidJumps;
3773+
3774+
IsSingleValueStmtResult(Kind kind)
3775+
: TheKind(kind), UnterminatedBranch(nullptr) {
3776+
assert(kind != Kind::UnterminatedBranch && kind != Kind::InvalidJumps);
3777+
}
3778+
3779+
IsSingleValueStmtResult(Kind kind, Stmt *unterminatedBranch)
3780+
: TheKind(kind), UnterminatedBranch(unterminatedBranch) {
3781+
assert(kind == Kind::UnterminatedBranch);
3782+
}
3783+
3784+
IsSingleValueStmtResult(Kind kind, std::vector<Stmt *> invalidJumps)
3785+
: TheKind(kind), InvalidJumps(std::move(invalidJumps)) {
3786+
assert(kind == Kind::InvalidJumps);
3787+
}
3788+
3789+
public:
3790+
static IsSingleValueStmtResult valid() {
3791+
return IsSingleValueStmtResult(Kind::Valid);
3792+
}
3793+
static IsSingleValueStmtResult unterminatedBranch(Stmt *branch) {
3794+
return IsSingleValueStmtResult(Kind::UnterminatedBranch, branch);
3795+
}
3796+
static IsSingleValueStmtResult nonExhaustiveIf() {
3797+
return IsSingleValueStmtResult(Kind::NonExhaustiveIf);
3798+
}
3799+
static IsSingleValueStmtResult noExpressionBranches() {
3800+
return IsSingleValueStmtResult(Kind::NoExpressionBranches);
3801+
}
3802+
static IsSingleValueStmtResult unhandledStmt() {
3803+
return IsSingleValueStmtResult(Kind::UnhandledStmt);
3804+
}
3805+
static IsSingleValueStmtResult circularReference() {
3806+
return IsSingleValueStmtResult(Kind::CircularReference);
3807+
}
3808+
static IsSingleValueStmtResult invalidJumps(std::vector<Stmt *> jumps) {
3809+
return IsSingleValueStmtResult(Kind::InvalidJumps, std::move(jumps));
3810+
}
3811+
static IsSingleValueStmtResult hasLabel() {
3812+
return IsSingleValueStmtResult(Kind::HasLabel);
3813+
}
3814+
3815+
Kind getKind() const { return TheKind; }
3816+
3817+
Stmt *getUnterminatedBranch() const {
3818+
assert(TheKind == Kind::UnterminatedBranch);
3819+
return UnterminatedBranch;
3820+
}
3821+
3822+
const std::vector<Stmt *> &getInvalidJumps() const {
3823+
assert(TheKind == Kind::InvalidJumps);
3824+
return InvalidJumps;
3825+
}
3826+
3827+
explicit operator bool() const {
3828+
return TheKind == Kind::Valid;
3829+
}
3830+
};
3831+
3832+
class IsSingleValueStmtRequest
3833+
: public SimpleRequest<IsSingleValueStmtRequest,
3834+
IsSingleValueStmtResult(const Stmt *),
3835+
RequestFlags::Cached> {
3836+
public:
3837+
using SimpleRequest::SimpleRequest;
3838+
3839+
private:
3840+
friend SimpleRequest;
3841+
3842+
IsSingleValueStmtResult
3843+
evaluate(Evaluator &evaluator, const Stmt *stmt) const;
3844+
3845+
public:
3846+
bool isCached() const { return true; }
3847+
};
3848+
37553849
/// Find the definition of a given macro.
37563850
class MacroDefinitionRequest
37573851
: public SimpleRequest<MacroDefinitionRequest,

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,9 @@ SWIFT_REQUEST(TypeChecker, ContinueTargetRequest,
443443
SWIFT_REQUEST(TypeChecker, GetTypeWrapperInitializer,
444444
ConstructorDecl *(NominalTypeDecl *),
445445
Cached, NoLocationInfo)
446+
SWIFT_REQUEST(TypeChecker, IsSingleValueStmtRequest,
447+
IsSingleValueStmtResult(const Stmt *),
448+
Cached, NoLocationInfo)
446449
SWIFT_REQUEST(TypeChecker, MacroDefinitionRequest,
447450
MacroDefinition(MacroDecl *),
448451
Cached, NoLocationInfo)

include/swift/Basic/Features.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,9 @@ EXPERIMENTAL_FEATURE(ParserRoundTrip, false)
136136
/// Swift parser.
137137
EXPERIMENTAL_FEATURE(ParserValidation, false)
138138

139+
/// Whether to allow 'if' and 'switch' statements to be treated as expressions.
140+
EXPERIMENTAL_FEATURE(StatementExpressions, false)
141+
139142
/// Whether to fold sequence expressions in the syntax tree produced by the
140143
/// Swift Swift parser.
141144
EXPERIMENTAL_FEATURE(ParserSequenceFolding, false)

include/swift/Parse/Parser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ namespace swift {
5050
class RequirementRepr;
5151
class SILParserStateBase;
5252
class ScopeInfo;
53+
class SingleValueStmtExpr;
5354
class SourceManager;
5455
class TupleType;
5556
class TypeLoc;

include/swift/Sema/CompletionContextFinder.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ namespace swift {
2323
class CompletionContextFinder : public ASTWalker {
2424
enum class ContextKind {
2525
FallbackExpression,
26+
SingleValueStmtExpr,
2627
StringInterpolation,
2728
SingleStmtClosure,
2829
MultiStmtClosure,
@@ -78,6 +79,10 @@ class CompletionContextFinder : public ASTWalker {
7879
return hasContext(ContextKind::StringInterpolation);
7980
}
8081

82+
bool locatedInSingleValueStmtExpr() const {
83+
return hasContext(ContextKind::SingleValueStmtExpr);
84+
}
85+
8186
bool hasCompletionExpr() const {
8287
return CompletionNode.dyn_cast<CodeCompletionExpr *>() != nullptr;
8388
}

include/swift/Sema/ConstraintLocator.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,16 @@ enum ContextualTypePurpose : uint8_t {
8585
CTP_ComposedPropertyWrapper, ///< Composed wrapper type expected to match
8686
///< former 'wrappedValue' type
8787

88+
CTP_SingleValueStmtBranch, ///< The contextual type for a branch in a single
89+
///< value statement expression.
90+
91+
// FIXME: This is only really for closures...
92+
CTP_SingleValueStmtBranchInSingleExprReturn, ///< The contextual type for a
93+
///< branch in a single value
94+
///< statement expression that's
95+
///< part of a single expression
96+
///< return.
97+
8898
CTP_ExprPattern, ///< `~=` operator application associated with expression
8999
/// pattern.
90100

@@ -292,6 +302,10 @@ class ConstraintLocator : public llvm::FoldingSetNode {
292302
/// Determine whether this locator is for a result builder body result type.
293303
bool isForResultBuilderBodyResult() const;
294304

305+
bool isForSingleValueStmtConjunction() const;
306+
307+
bool isForSingleValueStmtBranchInSingleExprReturn() const;
308+
295309
/// Determine whether this locator points directly to a given expression.
296310
template <typename E> bool directlyAt() const {
297311
if (auto *expr = getAnchor().dyn_cast<Expr *>())
@@ -883,6 +897,22 @@ class LocatorPathElt::TernaryBranch final : public StoredIntegerElement<1> {
883897
}
884898
};
885899

900+
/// The branch of a SingleValueStmtExpr. Note the stored index corresponds to
901+
/// the expression branches, i.e it skips statement branch indices.
902+
class LocatorPathElt::SingleValueStmtBranch final
903+
: public StoredIntegerElement<1> {
904+
public:
905+
SingleValueStmtBranch(unsigned exprIdx)
906+
: StoredIntegerElement(ConstraintLocator::SingleValueStmtBranch,
907+
exprIdx) {}
908+
909+
unsigned getExprBranchIndex() const { return getValue(); }
910+
911+
static bool classof(const LocatorPathElt *elt) {
912+
return elt->getKind() == ConstraintLocator::SingleValueStmtBranch;
913+
}
914+
};
915+
886916
class LocatorPathElt::PatternMatch final : public StoredPointerElement<Pattern> {
887917
public:
888918
PatternMatch(Pattern *pattern)

0 commit comments

Comments
 (0)