Skip to content

Commit 3b66a31

Browse files
committed
Model Pack Expressions and Pack Reifications
Pack expressions take a series of argument values and bundle them together as a pack - much like how a tuple expression bundles argument expressions into a tuple. Pack reification represents the operation that converts packs to tuples/scalar types in the AST. This is important since we want pack types in return positions to resolve to tuples contextually.
1 parent 06bc38f commit 3b66a31

File tree

10 files changed

+194
-2
lines changed

10 files changed

+194
-2
lines changed

include/swift/AST/Expr.h

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,10 @@ class alignas(8) Expr : public ASTAllocated<Expr> {
348348
IsPlaceholder : 1
349349
);
350350

351+
SWIFT_INLINE_BITFIELD_FULL(PackExpr, Expr, 32,
352+
: NumPadBits,
353+
NumElements : 32
354+
);
351355
} Bits;
352356

353357
private:
@@ -3314,6 +3318,18 @@ class BridgeToObjCExpr : public ImplicitConversionExpr {
33143318
}
33153319
};
33163320

3321+
/// ReifyPackExpr - Drop the pack structure and reify it either as a tuple or
3322+
/// single value.
3323+
class ReifyPackExpr : public ImplicitConversionExpr {
3324+
public:
3325+
ReifyPackExpr(Expr *subExpr, Type type)
3326+
: ImplicitConversionExpr(ExprKind::ReifyPack, subExpr, type) {}
3327+
3328+
static bool classof(const Expr *E) {
3329+
return E->getKind() == ExprKind::ReifyPack;
3330+
}
3331+
};
3332+
33173333
/// UnresolvedSpecializeExpr - Represents an explicit specialization using
33183334
/// a type parameter list (e.g. "Vector<Int>") that has not been resolved.
33193335
class UnresolvedSpecializeExpr final : public Expr,
@@ -5758,6 +5774,55 @@ class OneWayExpr : public Expr {
57585774
}
57595775
};
57605776

5777+
/// An expression node that aggregates a set of heterogeneous arguments into a
5778+
/// parameter pack suitable for passing off to a variadic generic function
5779+
/// argument.
5780+
///
5781+
/// There is no user-visible way to spell a pack expression, they are always
5782+
/// implicitly created at applies. As such, any appearance of pack types outside
5783+
/// of applies are illegal. In general, packs appearing in such positions should
5784+
/// have a \c ReifyPackExpr to convert them to a user-available AST type.
5785+
class PackExpr final : public Expr,
5786+
private llvm::TrailingObjects<PackExpr, Expr *> {
5787+
friend TrailingObjects;
5788+
5789+
size_t numTrailingObjects() const {
5790+
return getNumElements();
5791+
}
5792+
5793+
PackExpr(ArrayRef<Expr *> SubExprs, Type Ty);
5794+
5795+
public:
5796+
/// Create a pack.
5797+
static PackExpr *create(ASTContext &ctx, ArrayRef<Expr *> SubExprs, Type Ty);
5798+
5799+
/// Create an empty pack.
5800+
static PackExpr *createEmpty(ASTContext &ctx);
5801+
5802+
SourceLoc getLoc() const { return SourceLoc(); }
5803+
SourceRange getSourceRange() const { return SourceRange(); }
5804+
5805+
/// Retrieve the elements of this pack.
5806+
MutableArrayRef<Expr *> getElements() {
5807+
return { getTrailingObjects<Expr *>(), getNumElements() };
5808+
}
5809+
5810+
/// Retrieve the elements of this pack.
5811+
ArrayRef<Expr *> getElements() const {
5812+
return { getTrailingObjects<Expr *>(), getNumElements() };
5813+
}
5814+
5815+
unsigned getNumElements() const { return Bits.PackExpr.NumElements; }
5816+
5817+
Expr *getElement(unsigned i) const {
5818+
return getElements()[i];
5819+
}
5820+
void setElement(unsigned i, Expr *e) {
5821+
getElements()[i] = e;
5822+
}
5823+
5824+
static bool classof(const Expr *E) { return E->getKind() == ExprKind::Pack; }
5825+
};
57615826
inline bool Expr::isInfixOperator() const {
57625827
return isa<BinaryExpr>(this) || isa<IfExpr>(this) ||
57635828
isa<AssignExpr>(this) || isa<ExplicitCastExpr>(this);

include/swift/AST/ExprNodes.def

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,8 @@ ABSTRACT_EXPR(ImplicitConversion, Expr)
181181
EXPR(DifferentiableFunctionExtractOriginal, ImplicitConversionExpr)
182182
EXPR(LinearFunctionExtractOriginal, ImplicitConversionExpr)
183183
EXPR(LinearToDifferentiableFunction, ImplicitConversionExpr)
184-
EXPR_RANGE(ImplicitConversion, Load, LinearToDifferentiableFunction)
184+
EXPR(ReifyPack, ImplicitConversionExpr)
185+
EXPR_RANGE(ImplicitConversion, Load, ReifyPack)
185186
ABSTRACT_EXPR(ExplicitCast, Expr)
186187
ABSTRACT_EXPR(CheckedCast, ExplicitCastExpr)
187188
EXPR(ForcedCheckedCast, CheckedCastExpr)
@@ -203,7 +204,8 @@ EXPR(KeyPath, Expr)
203204
UNCHECKED_EXPR(KeyPathDot, Expr)
204205
UNCHECKED_EXPR(OneWay, Expr)
205206
EXPR(Tap, Expr)
206-
LAST_EXPR(Tap)
207+
EXPR(Pack, Expr)
208+
LAST_EXPR(Pack)
207209

208210
#undef EXPR_RANGE
209211
#undef LITERAL_EXPR

include/swift/AST/Types.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,13 @@ class alignas(1 << TypeAlignInBits) TypeBase
419419
Count : 32
420420
);
421421

422+
SWIFT_INLINE_BITFIELD_FULL(PackType, TypeBase, 32,
423+
: NumPadBits,
424+
425+
/// The number of elements of the tuple.
426+
Count : 32
427+
);
428+
422429
SWIFT_INLINE_BITFIELD_FULL(BoundGenericType, TypeBase, 32,
423430
: NumPadBits,
424431

lib/AST/ASTDumper.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2074,6 +2074,15 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
20742074
}
20752075
PrintWithColorRAII(OS, ParenthesisColor) << ')';
20762076
}
2077+
void visitPackExpr(PackExpr *E) {
2078+
printCommon(E, "pack_expr");
2079+
2080+
for (unsigned i = 0, e = E->getNumElements(); i != e; ++i) {
2081+
OS << '\n';
2082+
printRec(E->getElement(i));
2083+
}
2084+
PrintWithColorRAII(OS, ParenthesisColor) << ')';
2085+
}
20772086
void visitArrayExpr(ArrayExpr *E) {
20782087
printCommon(E, "array_expr");
20792088
PrintWithColorRAII(OS, LiteralValueColor) << " initializer=";
@@ -2220,6 +2229,11 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
22202229
printRec(E->getSubExpr());
22212230
PrintWithColorRAII(OS, ParenthesisColor) << ')';
22222231
}
2232+
void visitReifyPackExpr(ReifyPackExpr *E) {
2233+
printCommon(E, "reify_pack") << '\n';
2234+
printRec(E->getSubExpr());
2235+
PrintWithColorRAII(OS, ParenthesisColor) << ')';
2236+
}
22232237
void visitLoadExpr(LoadExpr *E) {
22242238
printCommon(E, "load_expr") << '\n';
22252239
printRec(E->getSubExpr());
@@ -3588,6 +3602,25 @@ namespace {
35883602
PrintWithColorRAII(OS, ParenthesisColor) << ')';
35893603
}
35903604

3605+
void visitPackType(PackType *T, StringRef label) {
3606+
printCommon(label, "pack_type");
3607+
printField("num_elements", T->getNumElements());
3608+
Indent += 2;
3609+
for (Type elt : T->getElementTypes()) {
3610+
OS.indent(Indent) << "(";
3611+
printRec(elt);
3612+
OS << ")";
3613+
}
3614+
Indent -= 2;
3615+
PrintWithColorRAII(OS, ParenthesisColor) << ')';
3616+
}
3617+
3618+
void visitPackExpansionType(PackExpansionType *T, StringRef label) {
3619+
printCommon(label, "pack_expansion_type");
3620+
printField("pattern", T->getPatternType());
3621+
PrintWithColorRAII(OS, ParenthesisColor) << ')';
3622+
}
3623+
35913624
void visitParenType(ParenType *T, StringRef label) {
35923625
printCommon(label, "paren_type");
35933626
dumpParameterFlags(T->getParameterFlags());

lib/AST/ASTWalker.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,16 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
602602
}
603603
return E;
604604
}
605+
Expr *visitPackExpr(PackExpr *E) {
606+
for (unsigned i = 0, e = E->getNumElements(); i != e; ++i)
607+
if (E->getElement(i)) {
608+
if (Expr *Elt = doIt(E->getElement(i)))
609+
E->setElement(i, Elt);
610+
else
611+
return nullptr;
612+
}
613+
return E;
614+
}
605615
Expr *visitSubscriptExpr(SubscriptExpr *E) {
606616
if (Expr *Base = doIt(E->getBase()))
607617
E->setBase(Base);

lib/AST/Expr.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,7 @@ ConcreteDeclRef Expr::getReferencedDecl(bool stopAtParenExpr) const {
397397
PASS_THROUGH_REFERENCE(BridgeFromObjC, getSubExpr);
398398
PASS_THROUGH_REFERENCE(ConditionalBridgeFromObjC, getSubExpr);
399399
PASS_THROUGH_REFERENCE(UnderlyingToOpaque, getSubExpr);
400+
PASS_THROUGH_REFERENCE(ReifyPack, getSubExpr);
400401
NO_REFERENCE(Coerce);
401402
NO_REFERENCE(ForcedCheckedCast);
402403
NO_REFERENCE(ConditionalCheckedCast);
@@ -414,6 +415,7 @@ ConcreteDeclRef Expr::getReferencedDecl(bool stopAtParenExpr) const {
414415
NO_REFERENCE(KeyPathDot);
415416
PASS_THROUGH_REFERENCE(OneWay, getSubExpr);
416417
NO_REFERENCE(Tap);
418+
NO_REFERENCE(Pack);
417419

418420
#undef SIMPLE_REFERENCE
419421
#undef NO_REFERENCE
@@ -723,6 +725,7 @@ bool Expr::canAppendPostfixExpression(bool appendingPostfixOperator) const {
723725
case ExprKind::BridgeFromObjC:
724726
case ExprKind::BridgeToObjC:
725727
case ExprKind::UnderlyingToOpaque:
728+
case ExprKind::ReifyPack:
726729
// Implicit conversion nodes have no syntax of their own; defer to the
727730
// subexpression.
728731
return cast<ImplicitConversionExpr>(this)->getSubExpr()
@@ -740,6 +743,7 @@ bool Expr::canAppendPostfixExpression(bool appendingPostfixOperator) const {
740743
case ExprKind::UnresolvedPattern:
741744
case ExprKind::EditorPlaceholder:
742745
case ExprKind::KeyPathDot:
746+
case ExprKind::Pack:
743747
return false;
744748

745749
case ExprKind::Tap:
@@ -906,6 +910,8 @@ bool Expr::isValidParentOfTypeExpr(Expr *typeExpr) const {
906910
case ExprKind::KeyPathDot:
907911
case ExprKind::OneWay:
908912
case ExprKind::Tap:
913+
case ExprKind::ReifyPack:
914+
case ExprKind::Pack:
909915
return false;
910916
}
911917

@@ -1116,6 +1122,21 @@ InOutExpr::InOutExpr(SourceLoc operLoc, Expr *subExpr, Type baseType,
11161122
baseType.isNull() ? baseType : InOutType::get(baseType)),
11171123
SubExpr(subExpr), OperLoc(operLoc) {}
11181124

1125+
VarargExpansionExpr *VarargExpansionExpr::createParamExpansion(ASTContext &ctx, Expr *E) {
1126+
assert(E->getType() && "Expansion must have fully-resolved type!");
1127+
return new (ctx) VarargExpansionExpr(E, /*implicit*/ true, E->getType());
1128+
}
1129+
1130+
VarargExpansionExpr *VarargExpansionExpr::createArrayExpansion(ASTContext &ctx, ArrayExpr *AE) {
1131+
assert(AE->getType() && "Expansion must have fully-resolved type!");
1132+
return new (ctx) VarargExpansionExpr(AE, /*implicit*/ true, AE->getType());
1133+
}
1134+
1135+
VarargExpansionExpr *VarargExpansionExpr::createTupleExpansion(ASTContext &ctx, TupleExpr *TE) {
1136+
assert(TE->getType() && "Expansion must have fully-resolved type!");
1137+
return new (ctx) VarargExpansionExpr(TE, /*implicit*/ true, TE->getType());
1138+
}
1139+
11191140
SequenceExpr *SequenceExpr::create(ASTContext &ctx, ArrayRef<Expr*> elements) {
11201141
assert(elements.size() & 1 && "even number of elements in sequence");
11211142
size_t bytes = totalSizeToAlloc<Expr *>(elements.size());
@@ -2250,6 +2271,30 @@ RegexLiteralExpr::createParsed(ASTContext &ctx, SourceLoc loc,
22502271
return new (ctx) RegexLiteralExpr(loc, regexText, /*implicit*/ false);
22512272
}
22522273

2274+
PackExpr::PackExpr(ArrayRef<Expr *> SubExprs, Type Ty)
2275+
: Expr(ExprKind::Pack, /*implicit*/ true, Ty) {
2276+
Bits.PackExpr.NumElements = SubExprs.size();
2277+
2278+
// Copy elements.
2279+
std::uninitialized_copy(SubExprs.begin(), SubExprs.end(),
2280+
getTrailingObjects<Expr *>());
2281+
}
2282+
2283+
PackExpr *PackExpr::create(ASTContext &ctx,
2284+
ArrayRef<Expr *> SubExprs,
2285+
Type Ty) {
2286+
assert(Ty->castTo<PackType>());
2287+
2288+
size_t size =
2289+
totalSizeToAlloc<Expr *>(SubExprs.size());
2290+
void *mem = ctx.Allocate(size, alignof(PackExpr));
2291+
return new (mem) PackExpr(SubExprs, Ty);
2292+
}
2293+
2294+
PackExpr *PackExpr::createEmpty(ASTContext &ctx) {
2295+
return create(ctx, {}, PackType::getEmpty(ctx));
2296+
}
2297+
22532298
void swift::simple_display(llvm::raw_ostream &out, const ClosureExpr *CE) {
22542299
if (!CE) {
22552300
out << "(null)";

lib/AST/Type.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ bool CanType::isReferenceTypeImpl(CanType type, const GenericSignatureImpl *sig,
231231
case TypeKind::BoundGenericStruct:
232232
case TypeKind::SILToken:
233233
case TypeKind::Pack:
234+
case TypeKind::PackExpansion:
234235
#define REF_STORAGE(Name, ...) \
235236
case TypeKind::Name##Storage:
236237
#include "swift/AST/ReferenceStorage.def"

lib/SILGen/SILGenExpr.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,7 @@ namespace {
436436
CollectionUpcastConversionExpr *E,
437437
SGFContext C);
438438
RValue visitBridgeToObjCExpr(BridgeToObjCExpr *E, SGFContext C);
439+
RValue visitReifyPackExpr(ReifyPackExpr *E, SGFContext C);
439440
RValue visitBridgeFromObjCExpr(BridgeFromObjCExpr *E, SGFContext C);
440441
RValue visitConditionalBridgeFromObjCExpr(ConditionalBridgeFromObjCExpr *E,
441442
SGFContext C);
@@ -460,6 +461,7 @@ namespace {
460461
RValue visitCoerceExpr(CoerceExpr *E, SGFContext C);
461462
RValue visitUnderlyingToOpaqueExpr(UnderlyingToOpaqueExpr *E, SGFContext C);
462463
RValue visitTupleExpr(TupleExpr *E, SGFContext C);
464+
RValue visitPackExpr(PackExpr *E, SGFContext C);
463465
RValue visitMemberRefExpr(MemberRefExpr *E, SGFContext C);
464466
RValue visitDynamicMemberRefExpr(DynamicMemberRefExpr *E, SGFContext C);
465467
RValue visitDotSyntaxBaseIgnoredExpr(DotSyntaxBaseIgnoredExpr *E,
@@ -1488,6 +1490,11 @@ RValueEmitter::visitBridgeToObjCExpr(BridgeToObjCExpr *E, SGFContext C) {
14881490
return RValue(SGF, E, result);
14891491
}
14901492

1493+
RValue
1494+
RValueEmitter::visitReifyPackExpr(ReifyPackExpr *E, SGFContext C) {
1495+
llvm_unreachable("Unimplemented!");
1496+
}
1497+
14911498
RValue RValueEmitter::visitArchetypeToSuperExpr(ArchetypeToSuperExpr *E,
14921499
SGFContext C) {
14931500
ManagedValue archetype = SGF.emitRValueAsSingleValue(E->getSubExpr());
@@ -2183,6 +2190,10 @@ RValue RValueEmitter::visitTupleExpr(TupleExpr *E, SGFContext C) {
21832190
return result;
21842191
}
21852192

2193+
RValue RValueEmitter::visitPackExpr(PackExpr *E, SGFContext C) {
2194+
llvm_unreachable("Unimplemented!");
2195+
}
2196+
21862197
RValue RValueEmitter::visitMemberRefExpr(MemberRefExpr *e,
21872198
SGFContext resultCtx) {
21882199
assert(!e->getType()->is<LValueType>() &&

lib/Sema/CSGen.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1720,6 +1720,18 @@ namespace {
17201720
return TupleType::get(elements, CS.getASTContext());
17211721
}
17221722

1723+
Type visitPackExpr(PackExpr *expr) {
1724+
// The type of a pack expression is simply a pack of the types of
1725+
// its subexpressions.
1726+
SmallVector<Type, 4> elements;
1727+
elements.reserve(expr->getNumElements());
1728+
for (unsigned i = 0, n = expr->getNumElements(); i != n; ++i) {
1729+
elements.emplace_back(CS.getType(expr->getElement(i)));
1730+
}
1731+
1732+
return PackType::get(CS.getASTContext(), elements);
1733+
}
1734+
17231735
Type visitSubscriptExpr(SubscriptExpr *expr) {
17241736
ValueDecl *decl = nullptr;
17251737
if (expr->hasDecl()) {

lib/Serialization/Serialization.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4386,6 +4386,12 @@ class Serializer::TypeSerializer : public TypeVisitor<TypeSerializer> {
43864386
llvm_unreachable("Unimplemented!");
43874387
}
43884388

4389+
void visitPackExpansionType(const PackExpansionType *pack) {
4390+
using namespace decls_block;
4391+
// serializeSimpleWrapper<ParenTypeLayout>(parenTy->getUnderlyingType());
4392+
llvm_unreachable("Unimplemented!");
4393+
}
4394+
43894395
void visitParenType(const ParenType *parenTy) {
43904396
using namespace decls_block;
43914397
assert(parenTy->getParameterFlags().isNone());

0 commit comments

Comments
 (0)