Skip to content

Commit 29f6c0d

Browse files
committed
[Parser] Parse 'each' as a contextual keyword applied to pack references.
1 parent 41298c2 commit 29f6c0d

File tree

5 files changed

+29
-5
lines changed

5 files changed

+29
-5
lines changed

lib/Parse/ParsePattern.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,8 @@ bool Parser::startsParameterName(bool isClosure) {
162162
// If the first name wasn't "isolated", we're done.
163163
if (!Tok.isContextualKeyword("isolated") &&
164164
!Tok.isContextualKeyword("some") &&
165-
!Tok.isContextualKeyword("any"))
165+
!Tok.isContextualKeyword("any") &&
166+
!Tok.isContextualKeyword("each"))
166167
return true;
167168

168169
// "isolated" can be an argument label, but it's also a contextual keyword,

lib/Parse/ParseType.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -780,8 +780,8 @@ Parser::parseTypeIdentifier(bool isParsingQualifiedDeclBaseType) {
780780
/// type-composition '&' type-simple
781781
ParserResult<TypeRepr>
782782
Parser::parseTypeSimpleOrComposition(Diag<> MessageID, ParseTypeReason reason) {
783-
// Check for the opaque modifier.
784-
// This is only semantically allowed in certain contexts, but we parse it
783+
// Check for the contextual keyword modifiers on types.
784+
// These are only semantically allowed in certain contexts, but we parse it
785785
// generally for diagnostics and recovery.
786786
SourceLoc opaqueLoc;
787787
SourceLoc anyLoc;
@@ -793,6 +793,16 @@ Parser::parseTypeSimpleOrComposition(Diag<> MessageID, ParseTypeReason reason) {
793793
// Treat any as a keyword.
794794
TokReceiver->registerTokenKindChange(Tok.getLoc(), tok::contextual_keyword);
795795
anyLoc = consumeToken();
796+
} else if (Tok.isContextualKeyword("each")) {
797+
// Treat 'each' as a keyword.
798+
TokReceiver->registerTokenKindChange(Tok.getLoc(), tok::contextual_keyword);
799+
SourceLoc eachLoc = consumeToken();
800+
ParserResult<TypeRepr> packRef = parseTypeSimple(MessageID, reason);
801+
if (packRef.isNull())
802+
return packRef;
803+
804+
auto *typeRepr = new (Context) PackReferenceTypeRepr(eachLoc, packRef.get());
805+
return makeParserResult(ParserStatus(packRef), typeRepr);
796806
}
797807

798808
auto applyOpaque = [&](TypeRepr *type) -> TypeRepr * {
@@ -1393,6 +1403,8 @@ bool Parser::canParseType() {
13931403
consumeToken();
13941404
} else if (Tok.isContextualKeyword("any")) {
13951405
consumeToken();
1406+
} else if (Tok.isContextualKeyword("each")) {
1407+
consumeToken();
13961408
}
13971409

13981410
switch (Tok.getKind()) {

lib/Sema/TypeCheckDecl.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2261,6 +2261,7 @@ static Type validateParameterType(ParamDecl *decl) {
22612261
// @escaping in this case.
22622262
options.setContext(TypeResolverContext::VariadicFunctionInput);
22632263
options |= TypeResolutionFlags::Direct;
2264+
options |= TypeResolutionFlags::AllowPackReferences;
22642265

22652266
// FIXME: This duplicates code found elsewhere
22662267
auto *patternRepr = packExpansionRepr->getPatternType();

lib/Sema/TypeCheckType.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4268,7 +4268,7 @@ NeverNullType TypeResolver::resolvePackReference(PackReferenceTypeRepr *repr,
42684268
ctx.Diags.diagnose(repr->getLoc(),
42694269
diag::pack_reference_outside_expansion,
42704270
packReference);
4271-
return packReference;
4271+
return ErrorType::get(ctx);
42724272
}
42734273

42744274
return packReference;

test/type/pack_expansion.swift

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,14 @@ struct Outer<T...> {
6363
struct AlsoGood<U...> {
6464
typealias Value = ((T, E<U... >)...)
6565
}
66-
}
66+
}
67+
68+
func packRef<T...>(_: (each T)...) where each T: P {}
69+
70+
func packMemberRef<T...>(_: (each T.T)...) where each T: P {}
71+
72+
// expected-error@+1 {{'each' cannot be applied to non-pack type 'Int'}}
73+
func invalidPackRef(_: each Int) {}
74+
75+
// expected-error@+1 {{pack reference 'T' can only appear in pack expansion or generic requirement}}
76+
func packRefOutsideExpansion<T...>(_: each T) {}

0 commit comments

Comments
 (0)