Skip to content

Commit 77da956

Browse files
authored
Merge pull request #31607 from rjmccall/unbraced-multiple-trailing-closures-5.3
[5.3] Implement SE-0279
2 parents dc9de24 + 41bebf9 commit 77da956

File tree

63 files changed

+2184
-577
lines changed

Some content is hidden

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

63 files changed

+2184
-577
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1750,5 +1750,16 @@ ERROR(availability_query_repeated_platform, none,
17501750
ERROR(unknown_syntax_entity, PointsToFirstBadToken,
17511751
"unknown %0 syntax exists in the source", (StringRef))
17521752

1753+
//------------------------------------------------------------------------------
1754+
// MARK: multiple trailing closures diagnostics
1755+
//------------------------------------------------------------------------------
1756+
ERROR(expected_argument_label_followed_by_closure_literal,none,
1757+
"expected an argument label followed by a closure literal", ())
1758+
ERROR(expected_closure_literal,none,
1759+
"expected a closure literal", ())
1760+
1761+
ERROR(expected_multiple_closures_block_rbrace,none,
1762+
"expected '}' at the end of a trailing closures block", ())
1763+
17531764
#define UNDEFINE_DIAGNOSTIC_MACROS
17541765
#include "DefineDiagnosticMacros.h"

include/swift/AST/Expr.h

Lines changed: 131 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,18 @@ namespace swift {
6767
class KeyPathExpr;
6868
class CaptureListExpr;
6969

70+
struct TrailingClosure {
71+
Identifier Label;
72+
SourceLoc LabelLoc;
73+
Expr *ClosureExpr;
74+
75+
TrailingClosure(Expr *closure)
76+
: TrailingClosure(Identifier(), SourceLoc(), closure) {}
77+
78+
TrailingClosure(Identifier label, SourceLoc labelLoc, Expr *closure)
79+
: Label(label), LabelLoc(labelLoc), ClosureExpr(closure) {}
80+
};
81+
7082
enum class ExprKind : uint8_t {
7183
#define EXPR(Id, Parent) Id,
7284
#define LAST_EXPR(Id) Last_Expr = Id,
@@ -200,10 +212,7 @@ class alignas(8) Expr {
200212
FieldNo : 32
201213
);
202214

203-
SWIFT_INLINE_BITFIELD_FULL(TupleExpr, Expr, 1+1+1+32,
204-
/// Whether this tuple has a trailing closure.
205-
HasTrailingClosure : 1,
206-
215+
SWIFT_INLINE_BITFIELD_FULL(TupleExpr, Expr, 1+1+32,
207216
/// Whether this tuple has any labels.
208217
HasElementNames : 1,
209218

@@ -533,6 +542,11 @@ class alignas(8) Expr {
533542
bool isSelfExprOf(const AbstractFunctionDecl *AFD,
534543
bool sameBase = false) const;
535544

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+
536550
/// Produce a mapping from each subexpression to its parent
537551
/// expression, with the provided expression serving as the root of
538552
/// the parent map.
@@ -1197,7 +1211,7 @@ class ObjectLiteralExpr final
11971211
ArrayRef<Identifier> argLabels,
11981212
ArrayRef<SourceLoc> argLabelLocs,
11991213
SourceLoc rParenLoc,
1200-
Expr *trailingClosure,
1214+
ArrayRef<TrailingClosure> trailingClosures,
12011215
bool implicit);
12021216

12031217
LiteralKind getLiteralKind() const {
@@ -1219,6 +1233,11 @@ class ObjectLiteralExpr final
12191233
return Bits.ObjectLiteralExpr.HasTrailingClosure;
12201234
}
12211235

1236+
/// Return the index of the unlabeled trailing closure argument.
1237+
Optional<unsigned> getUnlabeledTrailingClosureIndex() const {
1238+
return getArg()->getUnlabeledTrailingClosureIndexOfPackedArgument();
1239+
}
1240+
12221241
SourceLoc getSourceLoc() const { return PoundLoc; }
12231242
SourceRange getSourceRange() const {
12241243
return SourceRange(PoundLoc, Arg->getEndLoc());
@@ -1783,6 +1802,11 @@ class DynamicSubscriptExpr final
17831802
return Bits.DynamicSubscriptExpr.HasTrailingClosure;
17841803
}
17851804

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

17881812
SourceLoc getStartLoc() const { return getBase()->getStartLoc(); }
@@ -1825,7 +1849,7 @@ class UnresolvedMemberExpr final
18251849
ArrayRef<Identifier> argLabels,
18261850
ArrayRef<SourceLoc> argLabelLocs,
18271851
SourceLoc rParenLoc,
1828-
Expr *trailingClosure,
1852+
ArrayRef<TrailingClosure> trailingClosures,
18291853
bool implicit);
18301854

18311855
DeclNameRef getName() const { return Name; }
@@ -1852,6 +1876,11 @@ class UnresolvedMemberExpr final
18521876
return Bits.UnresolvedMemberExpr.HasTrailingClosure;
18531877
}
18541878

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

18571886
SourceLoc getStartLoc() const { return DotLoc; }
@@ -2033,6 +2062,11 @@ class ParenExpr : public IdentityExpr {
20332062
/// Whether this expression has a trailing closure as its argument.
20342063
bool hasTrailingClosure() const { return Bits.ParenExpr.HasTrailingClosure; }
20352064

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

@@ -2046,6 +2080,8 @@ class TupleExpr final : public Expr,
20462080
SourceLoc LParenLoc;
20472081
SourceLoc RParenLoc;
20482082

2083+
Optional<unsigned> FirstTrailingArgumentAt;
2084+
20492085
size_t numTrailingObjects(OverloadToken<Expr *>) const {
20502086
return getNumElements();
20512087
}
@@ -2072,11 +2108,11 @@ class TupleExpr final : public Expr,
20722108
return { getTrailingObjects<SourceLoc>(), getNumElements() };
20732109
}
20742110

2075-
TupleExpr(SourceLoc LParenLoc, ArrayRef<Expr *> SubExprs,
2076-
ArrayRef<Identifier> ElementNames,
2111+
TupleExpr(SourceLoc LParenLoc, SourceLoc RParenLoc,
2112+
ArrayRef<Expr *> SubExprs,
2113+
ArrayRef<Identifier> ElementNames,
20772114
ArrayRef<SourceLoc> ElementNameLocs,
2078-
SourceLoc RParenLoc, bool HasTrailingClosure, bool Implicit,
2079-
Type Ty);
2115+
Optional<unsigned> FirstTrailingArgumentAt, bool Implicit, Type Ty);
20802116

20812117
public:
20822118
/// Create a tuple.
@@ -2088,6 +2124,15 @@ class TupleExpr final : public Expr,
20882124
SourceLoc RParenLoc, bool HasTrailingClosure,
20892125
bool Implicit, Type Ty = Type());
20902126

2127+
static TupleExpr *create(ASTContext &ctx,
2128+
SourceLoc LParenLoc,
2129+
SourceLoc RParenLoc,
2130+
ArrayRef<Expr *> SubExprs,
2131+
ArrayRef<Identifier> ElementNames,
2132+
ArrayRef<SourceLoc> ElementNameLocs,
2133+
Optional<unsigned> FirstTrailingArgumentAt,
2134+
bool Implicit, Type Ty = Type());
2135+
20912136
/// Create an empty tuple.
20922137
static TupleExpr *createEmpty(ASTContext &ctx, SourceLoc LParenLoc,
20932138
SourceLoc RParenLoc, bool Implicit);
@@ -2101,8 +2146,25 @@ class TupleExpr final : public Expr,
21012146

21022147
SourceRange getSourceRange() const;
21032148

2149+
bool hasAnyTrailingClosures() const {
2150+
return (bool) FirstTrailingArgumentAt;
2151+
}
2152+
21042153
/// Whether this expression has a trailing closure as its argument.
2105-
bool hasTrailingClosure() const { return Bits.TupleExpr.HasTrailingClosure; }
2154+
bool hasTrailingClosure() const {
2155+
return FirstTrailingArgumentAt
2156+
? *FirstTrailingArgumentAt == getNumElements() - 1
2157+
: false;
2158+
}
2159+
2160+
bool hasMultipleTrailingClosures() const {
2161+
return FirstTrailingArgumentAt ? !hasTrailingClosure() : false;
2162+
}
2163+
2164+
Optional<unsigned>
2165+
getUnlabeledTrailingClosureIndexOfPackedArgument() const {
2166+
return FirstTrailingArgumentAt;
2167+
}
21062168

21072169
/// Retrieve the elements of this tuple.
21082170
MutableArrayRef<Expr*> getElements() {
@@ -2113,8 +2175,22 @@ class TupleExpr final : public Expr,
21132175
ArrayRef<Expr*> getElements() const {
21142176
return { getTrailingObjects<Expr *>(), getNumElements() };
21152177
}
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+
}
21162186

21172187
unsigned getNumElements() const { return Bits.TupleExpr.NumElements; }
2188+
2189+
unsigned getNumTrailingElements() const {
2190+
return FirstTrailingArgumentAt
2191+
? getNumElements() - *FirstTrailingArgumentAt
2192+
: 0;
2193+
}
21182194

21192195
Expr *getElement(unsigned i) const {
21202196
return getElements()[i];
@@ -2350,7 +2426,7 @@ class SubscriptExpr final : public LookupExpr,
23502426
ArrayRef<Identifier> indexArgLabels,
23512427
ArrayRef<SourceLoc> indexArgLabelLocs,
23522428
SourceLoc rSquareLoc,
2353-
Expr *trailingClosure,
2429+
ArrayRef<TrailingClosure> trailingClosures,
23542430
ConcreteDeclRef decl = ConcreteDeclRef(),
23552431
bool implicit = false,
23562432
AccessSemantics semantics
@@ -2374,6 +2450,11 @@ class SubscriptExpr final : public LookupExpr,
23742450
return Bits.SubscriptExpr.HasTrailingClosure;
23752451
}
23762452

2453+
/// Return the index of the unlabeled trailing closure argument.
2454+
Optional<unsigned> getUnlabeledTrailingClosureIndex() const {
2455+
return getIndex()->getUnlabeledTrailingClosureIndexOfPackedArgument();
2456+
}
2457+
23772458
/// Determine whether this subscript reference should bypass the
23782459
/// ordinary accessors.
23792460
AccessSemantics getAccessSemantics() const {
@@ -4230,6 +4311,9 @@ class ApplyExpr : public Expr {
42304311
/// Whether this application was written using a trailing closure.
42314312
bool hasTrailingClosure() const;
42324313

4314+
/// Return the index of the unlabeled trailing closure argument.
4315+
Optional<unsigned> getUnlabeledTrailingClosureIndex() const;
4316+
42334317
static bool classof(const Expr *E) {
42344318
return E->getKind() >= ExprKind::First_ApplyExpr &&
42354319
E->getKind() <= ExprKind::Last_ApplyExpr;
@@ -4267,13 +4351,14 @@ class CallExpr final : public ApplyExpr,
42674351
/// \param args The call arguments, not including a trailing closure (if any).
42684352
/// \param argLabels The argument labels, whose size must equal args.size(),
42694353
/// or which must be empty.
4270-
static CallExpr *
4271-
createImplicit(ASTContext &ctx, Expr *fn, ArrayRef<Expr *> args,
4272-
ArrayRef<Identifier> argLabels,
4273-
llvm::function_ref<Type(const Expr *)> getType =
4274-
[](const Expr *E) -> Type { return E->getType(); }) {
4275-
return create(ctx, fn, SourceLoc(), args, argLabels, { }, SourceLoc(),
4276-
/*trailingClosure=*/nullptr, /*implicit=*/true, getType);
4354+
static CallExpr *createImplicit(
4355+
ASTContext &ctx, Expr *fn, ArrayRef<Expr *> args,
4356+
ArrayRef<Identifier> argLabels,
4357+
llvm::function_ref<Type(const Expr *)> getType = [](const Expr *E) -> Type {
4358+
return E->getType();
4359+
}) {
4360+
return create(ctx, fn, SourceLoc(), args, argLabels, {}, SourceLoc(),
4361+
/*trailingClosures=*/{}, /*implicit=*/true, getType);
42774362
}
42784363

42794364
/// Create a new call expression.
@@ -4284,13 +4369,15 @@ class CallExpr final : public ApplyExpr,
42844369
/// or which must be empty.
42854370
/// \param argLabelLocs The locations of the argument labels, whose size must
42864371
/// equal args.size() or which must be empty.
4287-
/// \param trailingClosure The trailing closure, if any.
4288-
static CallExpr *
4289-
create(ASTContext &ctx, Expr *fn, SourceLoc lParenLoc, ArrayRef<Expr *> args,
4290-
ArrayRef<Identifier> argLabels, ArrayRef<SourceLoc> argLabelLocs,
4291-
SourceLoc rParenLoc, Expr *trailingClosure, bool implicit,
4292-
llvm::function_ref<Type(const Expr *)> getType =
4293-
[](const Expr *E) -> Type { return E->getType(); });
4372+
/// \param trailingClosures The list of trailing closures, if any.
4373+
static CallExpr *create(
4374+
ASTContext &ctx, Expr *fn, SourceLoc lParenLoc, ArrayRef<Expr *> args,
4375+
ArrayRef<Identifier> argLabels, ArrayRef<SourceLoc> argLabelLocs,
4376+
SourceLoc rParenLoc, ArrayRef<TrailingClosure> trailingClosures,
4377+
bool implicit,
4378+
llvm::function_ref<Type(const Expr *)> getType = [](const Expr *E) -> Type {
4379+
return E->getType();
4380+
});
42944381

42954382
SourceLoc getStartLoc() const {
42964383
SourceLoc fnLoc = getFn()->getStartLoc();
@@ -4309,9 +4396,14 @@ class CallExpr final : public ApplyExpr,
43094396
unsigned getNumArguments() const { return Bits.CallExpr.NumArgLabels; }
43104397
bool hasArgumentLabelLocs() const { return Bits.CallExpr.HasArgLabelLocs; }
43114398

4312-
/// Whether this call with written with a trailing closure.
4399+
/// Whether this call with written with a single trailing closure.
43134400
bool hasTrailingClosure() const { return Bits.CallExpr.HasTrailingClosure; }
43144401

4402+
/// Return the index of the unlabeled trailing closure argument.
4403+
Optional<unsigned> getUnlabeledTrailingClosureIndex() const {
4404+
return getArg()->getUnlabeledTrailingClosureIndexOfPackedArgument();
4405+
}
4406+
43154407
using TrailingCallArguments::getArgumentLabels;
43164408

43174409
/// Retrieve the expression that directly represents the callee.
@@ -5182,7 +5274,7 @@ class KeyPathExpr : public Expr {
51825274
ArrayRef<Identifier> indexArgLabels,
51835275
ArrayRef<SourceLoc> indexArgLabelLocs,
51845276
SourceLoc rSquareLoc,
5185-
Expr *trailingClosure);
5277+
ArrayRef<TrailingClosure> trailingClosures);
51865278

51875279
/// Create an unresolved component for a subscript.
51885280
///
@@ -5234,7 +5326,7 @@ class KeyPathExpr : public Expr {
52345326
ArrayRef<Identifier> indexArgLabels,
52355327
ArrayRef<SourceLoc> indexArgLabelLocs,
52365328
SourceLoc rSquareLoc,
5237-
Expr *trailingClosure,
5329+
ArrayRef<TrailingClosure> trailingClosures,
52385330
Type elementType,
52395331
ArrayRef<ProtocolConformanceRef> indexHashables);
52405332

@@ -5619,18 +5711,16 @@ inline const SourceLoc *CollectionExpr::getTrailingSourceLocs() const {
56195711
///
56205712
/// \param argLabelLocs The argument label locations, which might be updated by
56215713
/// this function.
5622-
Expr *packSingleArgument(ASTContext &ctx, SourceLoc lParenLoc,
5623-
ArrayRef<Expr *> args,
5624-
ArrayRef<Identifier> &argLabels,
5625-
ArrayRef<SourceLoc> &argLabelLocs,
5626-
SourceLoc rParenLoc,
5627-
Expr *trailingClosure, bool implicit,
5628-
SmallVectorImpl<Identifier> &argLabelsScratch,
5629-
SmallVectorImpl<SourceLoc> &argLabelLocsScratch,
5630-
llvm::function_ref<Type(const Expr *)> getType =
5631-
[](const Expr *E) -> Type {
5632-
return E->getType();
5633-
});
5714+
Expr *packSingleArgument(
5715+
ASTContext &ctx, SourceLoc lParenLoc, ArrayRef<Expr *> args,
5716+
ArrayRef<Identifier> &argLabels, ArrayRef<SourceLoc> &argLabelLocs,
5717+
SourceLoc rParenLoc, ArrayRef<TrailingClosure> trailingClosures,
5718+
bool implicit,
5719+
SmallVectorImpl<Identifier> &argLabelsScratch,
5720+
SmallVectorImpl<SourceLoc> &argLabelLocsScratch,
5721+
llvm::function_ref<Type(const Expr *)> getType = [](const Expr *E) -> Type {
5722+
return E->getType();
5723+
});
56345724

56355725
void simple_display(llvm::raw_ostream &out, const ClosureExpr *CE);
56365726
void simple_display(llvm::raw_ostream &out, const DefaultArgumentExpr *expr);

include/swift/AST/TrailingCallArguments.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,16 +82,14 @@ class TrailingCallArguments
8282
protected:
8383
/// Determine the total size to allocate.
8484
static size_t totalSizeToAlloc(ArrayRef<Identifier> argLabels,
85-
ArrayRef<SourceLoc> argLabelLocs,
86-
bool hasTrailingClosure) {
85+
ArrayRef<SourceLoc> argLabelLocs) {
8786
return TrailingObjects::template totalSizeToAlloc<Identifier, SourceLoc>(
8887
argLabels.size(), argLabelLocs.size());
8988
}
9089

9190
/// Initialize the actual call arguments.
9291
void initializeCallArguments(ArrayRef<Identifier> argLabels,
93-
ArrayRef<SourceLoc> argLabelLocs,
94-
bool hasTrailingClosure) {
92+
ArrayRef<SourceLoc> argLabelLocs) {
9593
if (!argLabels.empty()) {
9694
std::uninitialized_copy(argLabels.begin(), argLabels.end(),
9795
this->template getTrailingObjects<Identifier>());

0 commit comments

Comments
 (0)