Skip to content

Commit 2b13365

Browse files
authored
Merge pull request #67206 from rintaro/parse-each-self-rdar107450487
[Parse] Accept 'self' after 'each'
2 parents 2d238bc + ababa1e commit 2b13365

File tree

3 files changed

+44
-37
lines changed

3 files changed

+44
-37
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,6 +1399,10 @@ ERROR(expected_expr_after_copy, none,
13991399
"expected expression after 'copy'", ())
14001400
ERROR(expected_expr_after_borrow, none,
14011401
"expected expression after '_borrow'", ())
1402+
ERROR(expected_expr_after_each, none,
1403+
"expected expression after 'each'", ())
1404+
ERROR(expected_expr_after_repeat, none,
1405+
"expected expression after 'repeat'", ())
14021406

14031407
WARNING(move_consume_final_spelling, none,
14041408
"'_move' has been renamed to 'consume', and the '_move' spelling will be removed shortly", ())

lib/Parse/ParseExpr.cpp

Lines changed: 38 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,44 @@ ParserResult<Expr> Parser::parseExprSequenceElement(Diag<> message,
465465
}
466466
}
467467

468+
// 'any' followed by another identifier is an existential type.
469+
if (Tok.isContextualKeyword("any") &&
470+
peekToken().is(tok::identifier) &&
471+
!peekToken().isAtStartOfLine()) {
472+
ParserResult<TypeRepr> ty = parseType();
473+
auto *typeExpr = new (Context) TypeExpr(ty.get());
474+
return makeParserResult(typeExpr);
475+
}
476+
477+
// 'repeat' as an expression prefix is a pack expansion expression.
478+
if (Tok.is(tok::kw_repeat)) {
479+
SourceLoc repeatLoc = consumeToken();
480+
auto patternExpr = parseExprImpl(
481+
diag::expected_expr_after_repeat, isExprBasic);
482+
if (patternExpr.isNull())
483+
return patternExpr;
484+
485+
auto *expansion =
486+
PackExpansionExpr::create(Context, repeatLoc, patternExpr.get(),
487+
/*genericEnv*/ nullptr);
488+
return makeParserResult(expansion);
489+
}
490+
491+
// 'each' followed by another identifier is a pack element expr.
492+
if (Tok.isContextualKeyword("each") &&
493+
peekToken().isAny(tok::identifier, tok::kw_self, tok::dollarident,
494+
tok::code_complete) &&
495+
!peekToken().isAtStartOfLine()) {
496+
SourceLoc loc = consumeToken();
497+
ParserResult<Expr> ref =
498+
parseExprSequenceElement(diag::expected_expr_after_each, isExprBasic);
499+
if (ref.isNull())
500+
return ref;
501+
502+
auto *packRef = PackElementExpr::create(Context, loc, ref.get());
503+
return makeParserResult(packRef);
504+
}
505+
468506
SourceLoc tryLoc;
469507
bool hadTry = consumeIf(tok::kw_try, tryLoc);
470508
llvm::Optional<Token> trySuffix;
@@ -546,19 +584,6 @@ ParserResult<Expr> Parser::parseExprUnary(Diag<> Message, bool isExprBasic) {
546584
// First check to see if we have the start of a regex literal `/.../`.
547585
tryLexRegexLiteral(/*forUnappliedOperator*/ false);
548586

549-
// 'repeat' as an expression prefix is a pack expansion expression.
550-
if (Tok.is(tok::kw_repeat)) {
551-
SourceLoc repeatLoc = consumeToken();
552-
auto patternExpr = parseExpr(Message);
553-
if (patternExpr.isNull())
554-
return patternExpr;
555-
556-
auto *expansion =
557-
PackExpansionExpr::create(Context, repeatLoc, patternExpr.get(),
558-
/*genericEnv*/ nullptr);
559-
return makeParserResult(expansion);
560-
}
561-
562587
// Try parse an 'if' or 'switch' as an expression. Note we do this here in
563588
// parseExprUnary as we don't allow postfix syntax to hang off such
564589
// expressions to avoid ambiguities such as postfix '.member', which can
@@ -1715,28 +1740,6 @@ ParserResult<Expr> Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) {
17151740
return makeParserResult(new (Context) UnresolvedPatternExpr(pattern));
17161741
}
17171742

1718-
// 'any' followed by another identifier is an existential type.
1719-
if (Tok.isContextualKeyword("any") &&
1720-
peekToken().is(tok::identifier) &&
1721-
!peekToken().isAtStartOfLine()) {
1722-
ParserResult<TypeRepr> ty = parseType();
1723-
auto *typeExpr = new (Context) TypeExpr(ty.get());
1724-
return makeParserResult(typeExpr);
1725-
}
1726-
1727-
// 'each' followed by another identifier is a pack element expr.
1728-
if (Tok.isContextualKeyword("each") &&
1729-
peekToken().is(tok::identifier) &&
1730-
!peekToken().isAtStartOfLine()) {
1731-
SourceLoc loc = consumeToken();
1732-
ParserResult<Expr> ref = parseExpr(ID);
1733-
if (ref.isNull())
1734-
return ref;
1735-
1736-
auto *packRef = PackElementExpr::create(Context, loc, ref.get());
1737-
return makeParserResult(packRef);
1738-
}
1739-
17401743
LLVM_FALLTHROUGH;
17411744
}
17421745
case tok::kw_Self: // Self

test/Interpreter/Inputs/variadic_generic_library.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,14 @@ public struct Predicate<each Input> {
4444
builder: (repeat Variable<each Input>) -> Expr
4545
) where Expr: Expression<Bool> {
4646
self.variables = (repeat Variable<each Input>())
47-
self.expression = builder(repeat each variables)
47+
self.expression = builder(repeat each self.variables)
4848
}
4949

5050
public func evaluate(
5151
_ input: repeat each Input
5252
) throws -> Bool {
5353
return try expression.evaluate(
54-
.init(repeat (each variables, each input))
54+
.init(repeat (each self.variables, each input))
5555
)
5656
}
5757
}

0 commit comments

Comments
 (0)