diff --git a/include/swift/AST/DiagnosticsParse.def b/include/swift/AST/DiagnosticsParse.def index dfa6f57e42eac..65b7bdd616d30 100644 --- a/include/swift/AST/DiagnosticsParse.def +++ b/include/swift/AST/DiagnosticsParse.def @@ -1399,6 +1399,10 @@ ERROR(expected_expr_after_copy, none, "expected expression after 'copy'", ()) ERROR(expected_expr_after_borrow, none, "expected expression after '_borrow'", ()) +ERROR(expected_expr_after_each, none, + "expected expression after 'each'", ()) +ERROR(expected_expr_after_repeat, none, + "expected expression after 'repeat'", ()) WARNING(move_consume_final_spelling, none, "'_move' has been renamed to 'consume', and the '_move' spelling will be removed shortly", ()) diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 12c6431c902b5..883c8d5125b91 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -465,6 +465,44 @@ ParserResult Parser::parseExprSequenceElement(Diag<> message, } } + // 'any' followed by another identifier is an existential type. + if (Tok.isContextualKeyword("any") && + peekToken().is(tok::identifier) && + !peekToken().isAtStartOfLine()) { + ParserResult ty = parseType(); + auto *typeExpr = new (Context) TypeExpr(ty.get()); + return makeParserResult(typeExpr); + } + + // 'repeat' as an expression prefix is a pack expansion expression. + if (Tok.is(tok::kw_repeat)) { + SourceLoc repeatLoc = consumeToken(); + auto patternExpr = parseExprImpl( + diag::expected_expr_after_repeat, isExprBasic); + if (patternExpr.isNull()) + return patternExpr; + + auto *expansion = + PackExpansionExpr::create(Context, repeatLoc, patternExpr.get(), + /*genericEnv*/ nullptr); + return makeParserResult(expansion); + } + + // 'each' followed by another identifier is a pack element expr. + if (Tok.isContextualKeyword("each") && + peekToken().isAny(tok::identifier, tok::kw_self, tok::dollarident, + tok::code_complete) && + !peekToken().isAtStartOfLine()) { + SourceLoc loc = consumeToken(); + ParserResult ref = + parseExprSequenceElement(diag::expected_expr_after_each, isExprBasic); + if (ref.isNull()) + return ref; + + auto *packRef = PackElementExpr::create(Context, loc, ref.get()); + return makeParserResult(packRef); + } + SourceLoc tryLoc; bool hadTry = consumeIf(tok::kw_try, tryLoc); llvm::Optional trySuffix; @@ -546,19 +584,6 @@ ParserResult Parser::parseExprUnary(Diag<> Message, bool isExprBasic) { // First check to see if we have the start of a regex literal `/.../`. tryLexRegexLiteral(/*forUnappliedOperator*/ false); - // 'repeat' as an expression prefix is a pack expansion expression. - if (Tok.is(tok::kw_repeat)) { - SourceLoc repeatLoc = consumeToken(); - auto patternExpr = parseExpr(Message); - if (patternExpr.isNull()) - return patternExpr; - - auto *expansion = - PackExpansionExpr::create(Context, repeatLoc, patternExpr.get(), - /*genericEnv*/ nullptr); - return makeParserResult(expansion); - } - // Try parse an 'if' or 'switch' as an expression. Note we do this here in // parseExprUnary as we don't allow postfix syntax to hang off such // expressions to avoid ambiguities such as postfix '.member', which can @@ -1715,28 +1740,6 @@ ParserResult Parser::parseExprPrimary(Diag<> ID, bool isExprBasic) { return makeParserResult(new (Context) UnresolvedPatternExpr(pattern)); } - // 'any' followed by another identifier is an existential type. - if (Tok.isContextualKeyword("any") && - peekToken().is(tok::identifier) && - !peekToken().isAtStartOfLine()) { - ParserResult ty = parseType(); - auto *typeExpr = new (Context) TypeExpr(ty.get()); - return makeParserResult(typeExpr); - } - - // 'each' followed by another identifier is a pack element expr. - if (Tok.isContextualKeyword("each") && - peekToken().is(tok::identifier) && - !peekToken().isAtStartOfLine()) { - SourceLoc loc = consumeToken(); - ParserResult ref = parseExpr(ID); - if (ref.isNull()) - return ref; - - auto *packRef = PackElementExpr::create(Context, loc, ref.get()); - return makeParserResult(packRef); - } - LLVM_FALLTHROUGH; } case tok::kw_Self: // Self diff --git a/test/Interpreter/Inputs/variadic_generic_library.swift b/test/Interpreter/Inputs/variadic_generic_library.swift index 26e058e777221..8246104f1120b 100644 --- a/test/Interpreter/Inputs/variadic_generic_library.swift +++ b/test/Interpreter/Inputs/variadic_generic_library.swift @@ -44,14 +44,14 @@ public struct Predicate { builder: (repeat Variable) -> Expr ) where Expr: Expression { self.variables = (repeat Variable()) - self.expression = builder(repeat each variables) + self.expression = builder(repeat each self.variables) } public func evaluate( _ input: repeat each Input ) throws -> Bool { return try expression.evaluate( - .init(repeat (each variables, each input)) + .init(repeat (each self.variables, each input)) ) } }