Skip to content

Commit a835f01

Browse files
committed
WIP for a different syntax for multiple trailing closures
that allows arbitrary `label: {}` suffixes after an initial unlabeled closure. Type-checking is not yet correct, as well as code-completion and other kinds of tooling.
1 parent 62dff4a commit a835f01

17 files changed

+202
-359
lines changed

include/swift/AST/Expr.h

Lines changed: 57 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,11 @@ class alignas(8) Expr {
542542
bool isSelfExprOf(const AbstractFunctionDecl *AFD,
543543
bool sameBase = false) const;
544544

545+
/// Given that this is a packed argument expression of the sort that
546+
/// would be produced from packSingleArgument, return the index of the
547+
/// unlabeled trailing closure, if there is one.
548+
Optional<unsigned> getUnlabeledTrailingClosureIndexOfPackedArgument() const;
549+
545550
/// Produce a mapping from each subexpression to its parent
546551
/// expression, with the provided expression serving as the root of
547552
/// the parent map.
@@ -1206,8 +1211,6 @@ class ObjectLiteralExpr final
12061211
ArrayRef<Identifier> argLabels,
12071212
ArrayRef<SourceLoc> argLabelLocs,
12081213
SourceLoc rParenLoc,
1209-
SourceLoc trailingLBrace,
1210-
SourceLoc trailingRBrace,
12111214
ArrayRef<TrailingClosure> trailingClosures,
12121215
bool implicit);
12131216

@@ -1230,6 +1233,11 @@ class ObjectLiteralExpr final
12301233
return Bits.ObjectLiteralExpr.HasTrailingClosure;
12311234
}
12321235

1236+
/// Return the index of the unlabeled trailing closure argument.
1237+
Optional<unsigned> getUnlabeledTrailingClosureIndex() const {
1238+
return getArg()->getUnlabeledTrailingClosureIndexOfPackedArgument();
1239+
}
1240+
12331241
SourceLoc getSourceLoc() const { return PoundLoc; }
12341242
SourceRange getSourceRange() const {
12351243
return SourceRange(PoundLoc, Arg->getEndLoc());
@@ -1794,6 +1802,11 @@ class DynamicSubscriptExpr final
17941802
return Bits.DynamicSubscriptExpr.HasTrailingClosure;
17951803
}
17961804

1805+
/// Return the index of the unlabeled trailing closure argument.
1806+
Optional<unsigned> getUnlabeledTrailingClosureIndex() const {
1807+
return Index->getUnlabeledTrailingClosureIndexOfPackedArgument();
1808+
}
1809+
17971810
SourceLoc getLoc() const { return Index->getStartLoc(); }
17981811

17991812
SourceLoc getStartLoc() const { return getBase()->getStartLoc(); }
@@ -1836,8 +1849,6 @@ class UnresolvedMemberExpr final
18361849
ArrayRef<Identifier> argLabels,
18371850
ArrayRef<SourceLoc> argLabelLocs,
18381851
SourceLoc rParenLoc,
1839-
SourceLoc trailingLBrace,
1840-
SourceLoc trailingRBrace,
18411852
ArrayRef<TrailingClosure> trailingClosures,
18421853
bool implicit);
18431854

@@ -1865,6 +1876,11 @@ class UnresolvedMemberExpr final
18651876
return Bits.UnresolvedMemberExpr.HasTrailingClosure;
18661877
}
18671878

1879+
/// Return the index of the unlabeled trailing closure argument.
1880+
Optional<unsigned> getUnlabeledTrailingClosureIndex() const {
1881+
return getArgument()->getUnlabeledTrailingClosureIndexOfPackedArgument();
1882+
}
1883+
18681884
SourceLoc getLoc() const { return NameLoc.getBaseNameLoc(); }
18691885

18701886
SourceLoc getStartLoc() const { return DotLoc; }
@@ -2046,6 +2062,11 @@ class ParenExpr : public IdentityExpr {
20462062
/// Whether this expression has a trailing closure as its argument.
20472063
bool hasTrailingClosure() const { return Bits.ParenExpr.HasTrailingClosure; }
20482064

2065+
Optional<unsigned>
2066+
getUnlabeledTrailingClosureIndexOfPackedArgument() const {
2067+
return hasTrailingClosure() ? Optional<unsigned>(0) : None;
2068+
}
2069+
20492070
static bool classof(const Expr *E) { return E->getKind() == ExprKind::Paren; }
20502071
};
20512072

@@ -2059,9 +2080,6 @@ class TupleExpr final : public Expr,
20592080
SourceLoc LParenLoc;
20602081
SourceLoc RParenLoc;
20612082

2062-
SourceLoc TrailingLBraceLoc;
2063-
SourceLoc TrailingRBraceLoc;
2064-
20652083
Optional<unsigned> FirstTrailingArgumentAt;
20662084

20672085
size_t numTrailingObjects(OverloadToken<Expr *>) const {
@@ -2094,8 +2112,6 @@ class TupleExpr final : public Expr,
20942112
ArrayRef<Expr *> SubExprs,
20952113
ArrayRef<Identifier> ElementNames,
20962114
ArrayRef<SourceLoc> ElementNameLocs,
2097-
SourceLoc TrailingLBrace,
2098-
SourceLoc TrailingRBrace,
20992115
Optional<unsigned> FirstTrailingArgumentAt, bool Implicit, Type Ty);
21002116

21012117
public:
@@ -2114,8 +2130,6 @@ class TupleExpr final : public Expr,
21142130
ArrayRef<Expr *> SubExprs,
21152131
ArrayRef<Identifier> ElementNames,
21162132
ArrayRef<SourceLoc> ElementNameLocs,
2117-
SourceLoc TrailingLBrace,
2118-
SourceLoc TrailingRBrace,
21192133
Optional<unsigned> FirstTrailingArgumentAt,
21202134
bool Implicit, Type Ty = Type());
21212135

@@ -2132,8 +2146,9 @@ class TupleExpr final : public Expr,
21322146

21332147
SourceRange getSourceRange() const;
21342148

2135-
SourceLoc getTrailingLBraceLoc() const { return TrailingLBraceLoc; }
2136-
SourceLoc getTrailingRBraceLoc() const { return TrailingRBraceLoc; }
2149+
bool hasAnyTrailingClosures() const {
2150+
return (bool) FirstTrailingArgumentAt;
2151+
}
21372152

21382153
/// Whether this expression has a trailing closure as its argument.
21392154
bool hasTrailingClosure() const {
@@ -2146,6 +2161,11 @@ class TupleExpr final : public Expr,
21462161
return FirstTrailingArgumentAt ? !hasTrailingClosure() : false;
21472162
}
21482163

2164+
Optional<unsigned>
2165+
getUnlabeledTrailingClosureIndexOfPackedArgument() const {
2166+
return FirstTrailingArgumentAt;
2167+
}
2168+
21492169
/// Retrieve the elements of this tuple.
21502170
MutableArrayRef<Expr*> getElements() {
21512171
return { getTrailingObjects<Expr *>(), getNumElements() };
@@ -2155,6 +2175,14 @@ class TupleExpr final : public Expr,
21552175
ArrayRef<Expr*> getElements() const {
21562176
return { getTrailingObjects<Expr *>(), getNumElements() };
21572177
}
2178+
2179+
MutableArrayRef<Expr*> getTrailingElements() {
2180+
return getElements().take_back(getNumTrailingElements());
2181+
}
2182+
2183+
ArrayRef<Expr*> getTrailingElements() const {
2184+
return getElements().take_back(getNumTrailingElements());
2185+
}
21582186

21592187
unsigned getNumElements() const { return Bits.TupleExpr.NumElements; }
21602188

@@ -2398,8 +2426,6 @@ class SubscriptExpr final : public LookupExpr,
23982426
ArrayRef<Identifier> indexArgLabels,
23992427
ArrayRef<SourceLoc> indexArgLabelLocs,
24002428
SourceLoc rSquareLoc,
2401-
SourceLoc trailingLBrace,
2402-
SourceLoc trailingRBrace,
24032429
ArrayRef<TrailingClosure> trailingClosures,
24042430
ConcreteDeclRef decl = ConcreteDeclRef(),
24052431
bool implicit = false,
@@ -2424,6 +2450,11 @@ class SubscriptExpr final : public LookupExpr,
24242450
return Bits.SubscriptExpr.HasTrailingClosure;
24252451
}
24262452

2453+
/// Return the index of the unlabeled trailing closure argument.
2454+
Optional<unsigned> getUnlabeledTrailingClosureIndex() const {
2455+
return getIndex()->getUnlabeledTrailingClosureIndexOfPackedArgument();
2456+
}
2457+
24272458
/// Determine whether this subscript reference should bypass the
24282459
/// ordinary accessors.
24292460
AccessSemantics getAccessSemantics() const {
@@ -4221,6 +4252,9 @@ class ApplyExpr : public Expr {
42214252
/// Whether this application was written using a trailing closure.
42224253
bool hasTrailingClosure() const;
42234254

4255+
/// Return the index of the unlabeled trailing closure argument.
4256+
Optional<unsigned> getUnlabeledTrailingClosureIndex() const;
4257+
42244258
static bool classof(const Expr *E) {
42254259
return E->getKind() >= ExprKind::First_ApplyExpr &&
42264260
E->getKind() <= ExprKind::Last_ApplyExpr;
@@ -4264,8 +4298,7 @@ class CallExpr final : public ApplyExpr,
42644298
llvm::function_ref<Type(const Expr *)> getType =
42654299
[](const Expr *E) -> Type { return E->getType(); }) {
42664300
return create(ctx, fn, SourceLoc(), args, argLabels, {}, SourceLoc(),
4267-
SourceLoc(), SourceLoc(), /*trailingClosures=*/{},
4268-
/*implicit=*/true, getType);
4301+
/*trailingClosures=*/{}, /*implicit=*/true, getType);
42694302
}
42704303

42714304
/// Create a new call expression.
@@ -4280,8 +4313,8 @@ class CallExpr final : public ApplyExpr,
42804313
static CallExpr *
42814314
create(ASTContext &ctx, Expr *fn, SourceLoc lParenLoc, ArrayRef<Expr *> args,
42824315
ArrayRef<Identifier> argLabels, ArrayRef<SourceLoc> argLabelLocs,
4283-
SourceLoc rParenLoc, SourceLoc trailingLBrace, SourceLoc trailingRBrace,
4284-
ArrayRef<TrailingClosure> trailingClosures, bool implicit,
4316+
SourceLoc rParenLoc, ArrayRef<TrailingClosure> trailingClosures,
4317+
bool implicit,
42854318
llvm::function_ref<Type(const Expr *)> getType =
42864319
[](const Expr *E) -> Type { return E->getType(); });
42874320

@@ -4305,6 +4338,11 @@ class CallExpr final : public ApplyExpr,
43054338
/// Whether this call with written with a single trailing closure.
43064339
bool hasTrailingClosure() const { return Bits.CallExpr.HasTrailingClosure; }
43074340

4341+
/// Return the index of the unlabeled trailing closure argument.
4342+
Optional<unsigned> getUnlabeledTrailingClosureIndex() const {
4343+
return getArg()->getUnlabeledTrailingClosureIndexOfPackedArgument();
4344+
}
4345+
43084346
using TrailingCallArguments::getArgumentLabels;
43094347

43104348
/// Retrieve the expression that directly represents the callee.
@@ -5175,8 +5213,6 @@ class KeyPathExpr : public Expr {
51755213
ArrayRef<Identifier> indexArgLabels,
51765214
ArrayRef<SourceLoc> indexArgLabelLocs,
51775215
SourceLoc rSquareLoc,
5178-
SourceLoc trailingLBrace,
5179-
SourceLoc trailingRBrace,
51805216
ArrayRef<TrailingClosure> trailingClosures);
51815217

51825218
/// Create an unresolved component for a subscript.
@@ -5229,8 +5265,6 @@ class KeyPathExpr : public Expr {
52295265
ArrayRef<Identifier> indexArgLabels,
52305266
ArrayRef<SourceLoc> indexArgLabelLocs,
52315267
SourceLoc rSquareLoc,
5232-
SourceLoc trailingLBrace,
5233-
SourceLoc trailingRBrace,
52345268
ArrayRef<TrailingClosure> trailingClosures,
52355269
Type elementType,
52365270
ArrayRef<ProtocolConformanceRef> indexHashables);
@@ -5621,8 +5655,6 @@ Expr *packSingleArgument(ASTContext &ctx, SourceLoc lParenLoc,
56215655
ArrayRef<Identifier> &argLabels,
56225656
ArrayRef<SourceLoc> &argLabelLocs,
56235657
SourceLoc rParenLoc,
5624-
SourceLoc trailingLBrace,
5625-
SourceLoc trailingRBrace,
56265658
ArrayRef<TrailingClosure> trailingClosures,
56275659
bool implicit,
56285660
SmallVectorImpl<Identifier> &argLabelsScratch,

include/swift/Parse/Parser.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1567,20 +1567,13 @@ class Parser {
15671567
SmallVectorImpl<Identifier> &exprLabels,
15681568
SmallVectorImpl<SourceLoc> &exprLabelLocs,
15691569
SourceLoc &rightLoc,
1570-
SourceLoc &trailingLBrace,
1571-
SourceLoc &trailingRBrace,
15721570
SmallVectorImpl<TrailingClosure> &trailingClosures,
15731571
syntax::SyntaxKind Kind);
15741572

15751573
ParserStatus
15761574
parseTrailingClosures(bool isExprBasic, SourceRange calleeRange,
1577-
SourceLoc &LBrace, SourceLoc &RBrace,
15781575
SmallVectorImpl<TrailingClosure> &closures);
15791576

1580-
ParserStatus
1581-
parseMultipleTrailingClosures(SourceLoc &LBrace, SourceLoc &RBrace,
1582-
SmallVectorImpl<TrailingClosure> &closures);
1583-
15841577
/// Parse an object literal.
15851578
///
15861579
/// \param LK The literal kind as determined by the first token.

lib/AST/Attr.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1867,8 +1867,7 @@ CustomAttr *CustomAttr::create(ASTContext &ctx, SourceLoc atLoc, TypeLoc type,
18671867
Expr *arg = nullptr;
18681868
if (hasInitializer) {
18691869
arg = packSingleArgument(ctx, lParenLoc, args, argLabels, argLabelLocs,
1870-
rParenLoc, SourceLoc(), SourceLoc(),
1871-
/*trailingClosures=*/{}, implicit,
1870+
rParenLoc, /*trailingClosures=*/{}, implicit,
18721871
argLabelsScratch, argLabelLocsScratch);
18731872
}
18741873

0 commit comments

Comments
 (0)