Skip to content

Commit 06bc38f

Browse files
committed
Model PackExpansion Types
A PackExpansionType is the interface type of the explicit expansion of a corresponding set of variadic generic parameters. Pack expansions are spelled as single-element tuples with a single variadic component in most contexts except functions where they are allowed to appear without parentheses to match normal variadic declaration syntax. ``` func expand<T...>(_ xs: T...) -> (T...) ~~~~ ~~~~~~ ``` A pack expansion type comes equipped with a pattern type spelled before the ellipses - `T` in the examples above. This pattern type is the subject of the expansion of the pack that is tripped when its variadic generic parameter is substituted for a `PackType`.
1 parent 746aa1f commit 06bc38f

15 files changed

+148
-0
lines changed

include/swift/AST/TypeDifferenceVisitor.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,12 @@ class CanTypeDifferenceVisitor : public CanTypePairVisitor<Impl, bool> {
135135
type1->getElementTypes(),
136136
type2->getElementTypes());
137137
}
138+
139+
bool visitPackExpansionType(CanPackExpansionType type1,
140+
CanPackExpansionType type2) {
141+
return asImpl().visit(type1.getPatternType(), type2.getPatternType());
142+
}
143+
138144
bool visitTupleType(CanTupleType type1, CanTupleType type2) {
139145
return visitComponentArray(type1, type2,
140146
type1->getElements(), type2->getElements());

include/swift/AST/TypeMatcher.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,19 @@ class TypeMatcher {
166166
// Pack/non-pack mismatch.
167167
return mismatch(firstTuple.getPointer(), secondType, sugaredFirstType);
168168
}
169+
170+
bool visitPackExpansionType(CanPackExpansionType firstPE, Type secondType,
171+
Type sugaredFirstType) {
172+
if (auto secondInOut = secondType->getAs<PackExpansionType>()) {
173+
return this->visit(firstPE.getPatternType(),
174+
secondInOut->getPatternType(),
175+
sugaredFirstType->castTo<PackExpansionType>()
176+
->getPatternType());
177+
}
178+
179+
return mismatch(firstPE.getPointer(), secondType, sugaredFirstType);
180+
}
181+
169182
bool visitReferenceStorageType(CanReferenceStorageType firstStorage,
170183
Type secondType, Type sugaredFirstType) {
171184
auto _secondStorage = secondType->getCanonicalType();

include/swift/AST/TypeNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ TYPE(Existential, Type)
166166
TYPE(LValue, Type)
167167
TYPE(InOut, Type)
168168
TYPE(Pack, Type)
169+
TYPE(PackExpansion, Type)
169170
UNCHECKED_TYPE(TypeVariable, Type)
170171
ABSTRACT_SUGARED_TYPE(Sugar, Type)
171172
SUGARED_TYPE(Paren, SugarType)

include/swift/AST/Types.h

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6202,6 +6202,63 @@ BEGIN_CAN_TYPE_WRAPPER(PackType, Type)
62026202
}
62036203
END_CAN_TYPE_WRAPPER(PackType, Type)
62046204

6205+
/// PackExpansionType - The interface type of the explicit expansion of a
6206+
/// corresponding set of variadic generic parameters.
6207+
///
6208+
/// Pack expansions are spelled as single-element tuples with a single variadic
6209+
/// component in most contexts except functions where they are allowed to appear
6210+
/// without parentheses to match normal variadic declaration syntax.
6211+
///
6212+
/// \code
6213+
/// func expand<T...>(_ xs: T...) -> (T...)
6214+
/// ~~~~ ~~~~~~
6215+
/// \endcode
6216+
///
6217+
/// A pack expansion type comes equipped with a pattern type spelled before
6218+
/// the ellipses - \c T in the examples above. This pattern type is the subject
6219+
/// of the expansion of the pack that is tripped when its variadic generic
6220+
/// parameter is substituted for a \c PackType.
6221+
class PackExpansionType : public TypeBase, public llvm::FoldingSetNode {
6222+
friend class ASTContext;
6223+
6224+
Type patternType;
6225+
6226+
public:
6227+
/// Create a pack expansion type from the given pattern type.
6228+
///
6229+
/// It is not required that the pattern type actually contain a reference to
6230+
/// a variadic generic parameter.
6231+
static PackExpansionType *get(Type pattern);
6232+
6233+
public:
6234+
/// Retrieves the pattern type of this pack expansion.
6235+
Type getPatternType() const { return patternType; }
6236+
6237+
public:
6238+
void Profile(llvm::FoldingSetNodeID &ID) {
6239+
Profile(ID, getPatternType());
6240+
}
6241+
6242+
static void Profile(llvm::FoldingSetNodeID &ID, Type patternType);
6243+
6244+
// Implement isa/cast/dyncast/etc.
6245+
static bool classof(const TypeBase *T) {
6246+
return T->getKind() == TypeKind::PackExpansion;
6247+
}
6248+
6249+
private:
6250+
PackExpansionType(Type patternType, const ASTContext *CanCtx)
6251+
: TypeBase(TypeKind::PackExpansion, CanCtx,
6252+
patternType->getRecursiveProperties()), patternType(patternType) {
6253+
assert(patternType);
6254+
}
6255+
};
6256+
BEGIN_CAN_TYPE_WRAPPER(PackExpansionType, Type)
6257+
CanType getPatternType() const {
6258+
return CanType(getPointer()->getPatternType());
6259+
}
6260+
END_CAN_TYPE_WRAPPER(PackExpansionType, Type)
6261+
62056262
/// getASTContext - Return the ASTContext that this type belongs to.
62066263
inline ASTContext &TypeBase::getASTContext() {
62076264
// If this type is canonical, it has the ASTContext in it.

lib/AST/ASTMangler.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1170,6 +1170,7 @@ void ASTMangler::appendType(Type type, GenericSignature sig,
11701170
}
11711171

11721172
case TypeKind::Pack:
1173+
case TypeKind::PackExpansion:
11731174
assert(DWARFMangling && "sugared types are only legal for the debugger");
11741175
appendOperator("XSP");
11751176
llvm_unreachable("Unimplemented");

lib/AST/ASTPrinter.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4639,6 +4639,12 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
46394639
Printer << ")";
46404640
}
46414641

4642+
void visitPackExpansionType(PackExpansionType *T) {
4643+
Printer << "(";
4644+
visit(T->getPatternType());
4645+
Printer << "..." << ")";
4646+
}
4647+
46424648
void visitTupleType(TupleType *T) {
46434649
Printer.callPrintStructurePre(PrintStructureKind::TupleType);
46444650
SWIFT_DEFER { Printer.printStructurePost(PrintStructureKind::TupleType); };

lib/AST/TypeWalker.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ class Traversal : public TypeVisitor<Traversal, bool>
5656
return false;
5757
}
5858

59+
bool visitPackExpansionType(PackExpansionType *ty) {
60+
return doIt(ty->getPatternType());
61+
}
62+
5963
bool visitParenType(ParenType *ty) {
6064
return doIt(ty->getUnderlyingType());
6165
}

lib/IRGen/Fulfillment.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ static bool isLeafTypeMetadata(CanType type) {
5353
case TypeKind::LValue:
5454
case TypeKind::InOut:
5555
case TypeKind::DynamicSelf:
56+
case TypeKind::PackExpansion:
5657
llvm_unreachable("these types do not have metadata");
5758

5859
// All the builtin types are leaves.
@@ -79,6 +80,7 @@ static bool isLeafTypeMetadata(CanType type) {
7980

8081
case TypeKind::Pack:
8182
return cast<PackType>(type)->getNumElements() == 0;
83+
8284
// Nominal types might have generic parents.
8385
case TypeKind::Class:
8486
case TypeKind::Enum:

lib/IRGen/GenType.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2199,6 +2199,7 @@ const TypeInfo *TypeConverter::convertType(CanType ty) {
21992199
case TypeKind::SILToken:
22002200
llvm_unreachable("should not be asking for representation of a SILToken");
22012201
case TypeKind::Pack:
2202+
case TypeKind::PackExpansion:
22022203
llvm_unreachable("Unimplemented!");
22032204
}
22042205
}

lib/IRGen/IRGenDebugInfo.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1508,6 +1508,7 @@ class IRGenDebugInfoImpl : public IRGenDebugInfo {
15081508
}
15091509

15101510
case TypeKind::Pack:
1511+
case TypeKind::PackExpansion:
15111512
llvm_unreachable("Unimplemented!");
15121513

15131514
case TypeKind::Tuple: {

0 commit comments

Comments
 (0)