Skip to content

Commit 74c1431

Browse files
committed
Parse Pack{...} types in SIL mode
This is needed for general fidelity in SIL, since generic argument lists are used for a lot of different things that aren't restricted from containing multiple packs. I haven't actually done the work to use Pack structure to disambiguate the resolution of pack parameters, but this is a good start. We'll probably need something like this in source eventually, so there's no reason to regret adding all the infrastructure for it.
1 parent c16e9c1 commit 74c1431

File tree

10 files changed

+174
-0
lines changed

10 files changed

+174
-0
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -890,6 +890,10 @@ ERROR(deprecated_protocol_composition_single,none,
890890
ERROR(deprecated_any_composition,none,
891891
"'protocol<>' syntax has been removed; use 'Any' instead", ())
892892

893+
// Pack Types
894+
ERROR(expected_rbrace_pack_type_list,none,
895+
"expected '}' at end of pack type list", ())
896+
893897
// SIL box Types
894898
ERROR(sil_box_expected_var_or_let,none,
895899
"expected 'var' or 'let' to introduce SIL box field type", ())

include/swift/AST/TypeRepr.h

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,11 @@ class alignas(1 << TypeReprAlignInBits) TypeRepr
100100
NumFields : 32
101101
);
102102

103+
SWIFT_INLINE_BITFIELD_FULL(PackTypeRepr, TypeRepr, 32,
104+
/// The number of elements contained.
105+
NumElements : 32
106+
);
107+
103108
} Bits;
104109

105110
TypeRepr(TypeReprKind K) {
@@ -758,6 +763,54 @@ class PackExpansionTypeRepr final : public TypeRepr {
758763
friend class TypeRepr;
759764
};
760765

766+
/// An explicit pack grouping, `Pack{...}`.
767+
///
768+
/// This allows packs to be explicitly grouped. It is currently only
769+
/// allowed in SIL files.
770+
class PackTypeRepr final
771+
: public TypeRepr,
772+
private llvm::TrailingObjects<PackTypeRepr, TypeRepr *> {
773+
friend TrailingObjects;
774+
SourceLoc KeywordLoc;
775+
SourceRange BraceLocs;
776+
777+
size_t numTrailingObjects(OverloadToken<TypeRepr*>) const {
778+
return Bits.PackTypeRepr.NumElements;
779+
}
780+
781+
PackTypeRepr(SourceLoc keywordLoc, SourceRange braceLocs,
782+
ArrayRef<TypeRepr*> elements);
783+
public:
784+
static PackTypeRepr *create(const ASTContext &ctx,
785+
SourceLoc keywordLoc,
786+
SourceRange braceLocs,
787+
ArrayRef<TypeRepr*> elements);
788+
789+
SourceLoc getKeywordLoc() const { return KeywordLoc; }
790+
SourceRange getBracesRange() const { return BraceLocs; }
791+
792+
MutableArrayRef<TypeRepr*> getMutableElements() {
793+
return llvm::makeMutableArrayRef(getTrailingObjects<TypeRepr*>(),
794+
Bits.PackTypeRepr.NumElements);
795+
}
796+
ArrayRef<TypeRepr*> getElements() const {
797+
return llvm::makeArrayRef(getTrailingObjects<TypeRepr*>(),
798+
Bits.PackTypeRepr.NumElements);
799+
}
800+
801+
static bool classof(const TypeRepr *T) {
802+
return T->getKind() == TypeReprKind::Pack;
803+
}
804+
static bool classof(const PackTypeRepr *T) { return true; }
805+
806+
private:
807+
SourceLoc getStartLocImpl() const { return KeywordLoc; }
808+
SourceLoc getEndLocImpl() const { return BraceLocs.End; }
809+
SourceLoc getLocImpl() const { return KeywordLoc; }
810+
void printImpl(ASTPrinter &Printer, const PrintOptions &Opts) const;
811+
friend class TypeRepr;
812+
};
813+
761814
/// A pack reference spelled with the \c each keyword.
762815
///
763816
/// Pack references can only appear inside pack expansions and in
@@ -1398,6 +1451,7 @@ inline bool TypeRepr::isSimple() const {
13981451
case TypeReprKind::ImplicitlyUnwrappedOptional:
13991452
case TypeReprKind::Vararg:
14001453
case TypeReprKind::PackExpansion:
1454+
case TypeReprKind::Pack:
14011455
case TypeReprKind::Tuple:
14021456
case TypeReprKind::Fixed:
14031457
case TypeReprKind::Array:

include/swift/AST/TypeReprNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ TYPEREPR(Protocol, TypeRepr)
6565
TYPEREPR(OpaqueReturn, TypeRepr)
6666
TYPEREPR(NamedOpaqueReturn, TypeRepr)
6767
TYPEREPR(Existential, TypeRepr)
68+
TYPEREPR(Pack, TypeRepr)
6869
TYPEREPR(PackReference, TypeRepr)
6970
TYPEREPR(Placeholder, TypeRepr)
7071
ABSTRACT_TYPEREPR(Specifier, TypeRepr)

lib/AST/ASTDumper.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3174,6 +3174,13 @@ class PrintTypeRepr : public TypeReprVisitor<PrintTypeRepr> {
31743174
PrintWithColorRAII(OS, ParenthesisColor) << ')';
31753175
}
31763176

3177+
void visitPackTypeRepr(PackTypeRepr *T) {
3178+
printCommon("pack") << '\n';
3179+
for (auto elt : T->getElements())
3180+
printRec(elt);
3181+
PrintWithColorRAII(OS, ParenthesisColor) << ')';
3182+
}
3183+
31773184
void visitPackExpansionTypeRepr(PackExpansionTypeRepr *T) {
31783185
printCommon("pack_expansion") << '\n';
31793186
printRec(T->getPatternType());

lib/AST/ASTWalker.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2007,6 +2007,13 @@ bool Traversal::visitVarargTypeRepr(VarargTypeRepr *T) {
20072007
return doIt(T->getElementType());
20082008
}
20092009

2010+
bool Traversal::visitPackTypeRepr(PackTypeRepr *T) {
2011+
for (auto &elem : T->getMutableElements())
2012+
if (doIt(elem))
2013+
return true;
2014+
return false;
2015+
}
2016+
20102017
bool Traversal::visitPackExpansionTypeRepr(PackExpansionTypeRepr *T) {
20112018
return doIt(T->getPatternType());
20122019
}

lib/AST/NameLookup.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2552,6 +2552,7 @@ directReferencesForTypeRepr(Evaluator &evaluator,
25522552
case TypeReprKind::Shared:
25532553
case TypeReprKind::SILBox:
25542554
case TypeReprKind::Placeholder:
2555+
case TypeReprKind::Pack:
25552556
return { };
25562557

25572558
case TypeReprKind::OpaqueReturn:

lib/AST/TypeRepr.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,24 @@ MemberTypeRepr *MemberTypeRepr::create(const ASTContext &Ctx,
397397
return create(Ctx, Components.front(), Components.drop_front());
398398
}
399399

400+
PackTypeRepr::PackTypeRepr(SourceLoc keywordLoc, SourceRange braceLocs,
401+
ArrayRef<TypeRepr*> elements)
402+
: TypeRepr(TypeReprKind::Pack),
403+
KeywordLoc(keywordLoc), BraceLocs(braceLocs) {
404+
Bits.PackTypeRepr.NumElements = elements.size();
405+
memcpy(getTrailingObjects<TypeRepr*>(), elements.data(),
406+
elements.size() * sizeof(TypeRepr*));
407+
}
408+
409+
PackTypeRepr *PackTypeRepr::create(const ASTContext &ctx,
410+
SourceLoc keywordLoc,
411+
SourceRange braceLocs,
412+
ArrayRef<TypeRepr*> elements) {
413+
auto size = totalSizeToAlloc<TypeRepr*>(elements.size());
414+
auto mem = ctx.Allocate(size, alignof(PackTypeRepr));
415+
return new (mem) PackTypeRepr(keywordLoc, braceLocs, elements);
416+
}
417+
400418
SILBoxTypeRepr *SILBoxTypeRepr::create(ASTContext &C,
401419
GenericParamList *GenericParams,
402420
SourceLoc LBraceLoc, ArrayRef<Field> Fields,
@@ -434,6 +452,18 @@ void VarargTypeRepr::printImpl(ASTPrinter &Printer,
434452
Printer << "...";
435453
}
436454

455+
void PackTypeRepr::printImpl(ASTPrinter &Printer,
456+
const PrintOptions &Opts) const {
457+
Printer.printKeyword("Pack", Opts);
458+
Printer << "{";
459+
auto elts = getElements();
460+
for (size_t i = 0, e = elts.size(); i != e; ++i) {
461+
if (i) Printer << ", ";
462+
printTypeRepr(elts[i], Printer, Opts);
463+
}
464+
Printer << "}";
465+
}
466+
437467
void PackExpansionTypeRepr::printImpl(ASTPrinter &Printer,
438468
const PrintOptions &Opts) const {
439469
Printer.printKeyword("repeat", Opts, /*Suffix=*/" ");

lib/Parse/ParseType.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ LayoutConstraint Parser::parseLayoutConstraint(Identifier LayoutConstraintID) {
160160
/// type-collection
161161
/// type-array
162162
/// '_'
163+
/// 'Pack' '{' (type (',' type)*)? '}' (only in SIL files)a
163164
ParserResult<TypeRepr> Parser::parseTypeSimple(
164165
Diag<> MessageID, ParseTypeReason reason) {
165166
ParserResult<TypeRepr> ty;
@@ -700,6 +701,34 @@ Parser::parseTypeIdentifier(bool isParsingQualifiedDeclBaseType) {
700701

701702
return nullptr;
702703
}
704+
705+
// In SIL files (not just when parsing SIL types), accept the
706+
// Pack{} syntax for spelling variadic type packs.
707+
if (SIL && Tok.isContextualKeyword("Pack") &&
708+
peekToken().is(tok::l_brace)) {
709+
TokReceiver->registerTokenKindChange(Tok.getLoc(), tok::contextual_keyword);
710+
SourceLoc keywordLoc = consumeToken(tok::identifier);
711+
SourceLoc lbLoc = consumeToken(tok::l_brace);
712+
SourceLoc rbLoc;
713+
SmallVector<TypeRepr*, 8> elements;
714+
auto status = parseList(tok::r_brace, lbLoc, rbLoc,
715+
/*AllowSepAfterLast=*/false,
716+
diag::expected_rbrace_pack_type_list,
717+
[&] () -> ParserStatus {
718+
auto element = parseType(diag::expected_type);
719+
if (element.hasCodeCompletion())
720+
return makeParserCodeCompletionStatus();
721+
if (element.isNull())
722+
return makeParserError();
723+
elements.push_back(element.get());
724+
return makeParserSuccess();
725+
});
726+
727+
return makeParserResult(status,
728+
PackTypeRepr::create(Context, keywordLoc, SourceRange(lbLoc, rbLoc),
729+
elements));
730+
}
731+
703732
ParserStatus Status;
704733
SmallVector<IdentTypeRepr *, 4> ComponentsR;
705734
SourceLoc EndLoc;

lib/Sema/TypeCheckType.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ static unsigned getGenericRequirementKind(TypeResolutionOptions options) {
141141
case TypeResolverContext::None:
142142
case TypeResolverContext::Inherited:
143143
case TypeResolverContext::FunctionInput:
144+
case TypeResolverContext::PackElement:
144145
case TypeResolverContext::TupleElement:
145146
case TypeResolverContext::GenericArgument:
146147
case TypeResolverContext::ProtocolGenericArgument:
@@ -2034,6 +2035,8 @@ namespace {
20342035
TypeResolutionOptions options);
20352036
NeverNullType resolveVarargType(VarargTypeRepr *repr,
20362037
TypeResolutionOptions options);
2038+
NeverNullType resolvePackType(PackTypeRepr *repr,
2039+
TypeResolutionOptions options);
20372040
NeverNullType resolvePackExpansionType(PackExpansionTypeRepr *repr,
20382041
TypeResolutionOptions options);
20392042
NeverNullType resolvePackReference(PackReferenceTypeRepr *repr,
@@ -2231,6 +2234,9 @@ NeverNullType TypeResolver::resolveType(TypeRepr *repr,
22312234
case TypeReprKind::Vararg:
22322235
return resolveVarargType(cast<VarargTypeRepr>(repr), options);
22332236

2237+
case TypeReprKind::Pack:
2238+
return resolvePackType(cast<PackTypeRepr>(repr), options);
2239+
22342240
case TypeReprKind::PackExpansion:
22352241
return resolvePackExpansionType(cast<PackExpansionTypeRepr>(repr), options);
22362242

@@ -4108,6 +4114,7 @@ NeverNullType TypeResolver::resolveImplicitlyUnwrappedOptionalType(
41084114
case TypeResolverContext::PatternBindingDecl:
41094115
doDiag = !isDirect;
41104116
break;
4117+
case TypeResolverContext::PackElement:
41114118
case TypeResolverContext::TupleElement:
41124119
case TypeResolverContext::GenericArgument:
41134120
case TypeResolverContext::ProtocolGenericArgument:
@@ -4220,6 +4227,32 @@ NeverNullType TypeResolver::resolveVarargType(VarargTypeRepr *repr,
42204227
return element;
42214228
}
42224229

4230+
NeverNullType TypeResolver::resolvePackType(PackTypeRepr *repr,
4231+
TypeResolutionOptions options) {
4232+
// This form is currently only allowed in SIL, so we're lax about
4233+
// where we allow this. If this is ever made a proper language feature,
4234+
// it should only be allowed in contexts where an expansion would be
4235+
// allowed and where structure could be ambiguous. That really just
4236+
// means generic argument lists.
4237+
//
4238+
// Its presence should also affect how arguments are implicitly grouped
4239+
// into packs, of course.
4240+
4241+
auto elementReprs = repr->getElements();
4242+
SmallVector<Type, 8> elementTypes;
4243+
elementTypes.reserve(elementReprs.size());
4244+
4245+
auto elementOptions = options;
4246+
elementOptions.setContext(TypeResolverContext::PackElement);
4247+
4248+
for (auto elementRepr : elementReprs) {
4249+
auto elementType = resolveType(elementRepr, elementOptions);
4250+
elementTypes.push_back(elementType);
4251+
}
4252+
4253+
return PackType::get(getASTContext(), elementTypes);
4254+
}
4255+
42234256
NeverNullType TypeResolver::resolvePackExpansionType(PackExpansionTypeRepr *repr,
42244257
TypeResolutionOptions options) {
42254258
auto &ctx = getASTContext();
@@ -4789,6 +4822,7 @@ class ExistentialTypeVisitor
47894822
case TypeReprKind::Placeholder:
47904823
case TypeReprKind::CompileTimeConst:
47914824
case TypeReprKind::Vararg:
4825+
case TypeReprKind::Pack:
47924826
case TypeReprKind::PackExpansion:
47934827
case TypeReprKind::PackReference:
47944828
return false;

lib/Sema/TypeCheckType.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,9 @@ enum class TypeResolverContext : uint8_t {
9292
/// Whether we are checking a tuple element type.
9393
TupleElement,
9494

95+
/// Whether we are checking a pack element type.
96+
PackElement,
97+
9598
/// Whether we are checking the parameter list of a function.
9699
AbstractFunctionDecl,
97100

@@ -253,6 +256,7 @@ class TypeResolutionOptions {
253256
case Context::GenericArgument:
254257
case Context::ProtocolGenericArgument:
255258
case Context::TupleElement:
259+
case Context::PackElement:
256260
case Context::FunctionInput:
257261
case Context::VariadicFunctionInput:
258262
case Context::InoutFunctionInput:
@@ -297,6 +301,7 @@ class TypeResolutionOptions {
297301
case Context::None:
298302
case Context::GenericArgument:
299303
case Context::ProtocolGenericArgument:
304+
case Context::PackElement:
300305
case Context::TupleElement:
301306
case Context::InExpression:
302307
case Context::ExplicitCastExpr:
@@ -326,6 +331,7 @@ class TypeResolutionOptions {
326331
switch (context) {
327332
case Context::FunctionInput:
328333
case Context::VariadicFunctionInput:
334+
case Context::PackElement:
329335
case Context::TupleElement:
330336
case Context::GenericArgument:
331337
return true;
@@ -379,6 +385,7 @@ class TypeResolutionOptions {
379385
case Context::None:
380386
case Context::Inherited:
381387
case Context::FunctionInput:
388+
case Context::PackElement:
382389
case Context::TupleElement:
383390
case Context::GenericArgument:
384391
case Context::ProtocolGenericArgument:

0 commit comments

Comments
 (0)