about summary refs log tree commit diff
path: root/src/libsyntax/parse/parser/expr.rs
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-08-26 23:55:44 +0200
committerGitHub <noreply@github.com>2019-08-26 23:55:44 +0200
commit7dc3c934e85a12bd48abf749d52c4be69e7eed5b (patch)
tree20000b371a3ae2118f2740f748f98645376479ab /src/libsyntax/parse/parser/expr.rs
parent44cfa7823d25ca52e42e23aad7dec22e4626f892 (diff)
parent2bd27fbdfe309f3f6abd76f72f379247d49048b7 (diff)
downloadrust-7dc3c934e85a12bd48abf749d52c4be69e7eed5b.tar.gz
rust-7dc3c934e85a12bd48abf749d52c4be69e7eed5b.zip
Rollup merge of #63693 - Centril:polish-parse-or-pats, r=estebank
Fully implement or-pattern parsing

Builds upon the initial parsing in https://github.com/rust-lang/rust/pull/61708 to fully implement or-pattern (`p | q`) parsing as specified in [the grammar section of RFC 2535](https://github.com/rust-lang/rfcs/blob/master/text/2535-or-patterns.md#grammar).

Noteworthy:

- We allow or-patterns in `[p | q, ...]`.
- We allow or-patterns in `let` statements and `for` expressions including with leading `|`.
- We improve recovery for `p || q` (+ tests for that in `multiple-pattern-typo.rs`).
- We improve recovery for `| p | q` in inner patterns (tests in `or-patterns-syntactic-fail.rs`).
- We rigorously test or-pattern parsing (in `or-patterns-syntactic-{pass,fail}.rs`).
- We harden the feature gating tests.
- We do **_not_** change `ast.rs`. That is, `ExprKind::Let.0` and `Arm.pats` still accept `Vec<P<Pat>>`.
   I was starting work on that but it would be cleaner to do this in a separate PR so this one has a narrower scope.

cc @dlrobertson
cc the tracking issue https://github.com/rust-lang/rust/issues/54883.

r? @estebank
Diffstat (limited to 'src/libsyntax/parse/parser/expr.rs')
-rw-r--r--src/libsyntax/parse/parser/expr.rs17
1 files changed, 10 insertions, 7 deletions
diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs
index 5da9b75d53b..f7c090b5135 100644
--- a/src/libsyntax/parse/parser/expr.rs
+++ b/src/libsyntax/parse/parser/expr.rs
@@ -1,6 +1,7 @@
 use super::{Parser, PResult, Restrictions, PrevTokenKind, TokenType, PathStyle};
 use super::{BlockMode, SemiColonMode};
 use super::{SeqSep, TokenExpectType};
+use super::pat::{GateOr, PARAM_EXPECTED};
 
 use crate::maybe_recover_from_interpolated_ty_qpath;
 use crate::ptr::P;
@@ -1175,7 +1176,7 @@ impl<'a> Parser<'a> {
     fn parse_fn_block_arg(&mut self) -> PResult<'a, Arg> {
         let lo = self.token.span;
         let attrs = self.parse_arg_attributes()?;
-        let pat = self.parse_pat(Some("argument name"))?;
+        let pat = self.parse_pat(PARAM_EXPECTED)?;
         let t = if self.eat(&token::Colon) {
             self.parse_ty()?
         } else {
@@ -1241,11 +1242,12 @@ impl<'a> Parser<'a> {
         Ok(cond)
     }
 
-    /// Parses a `let $pats = $expr` pseudo-expression.
+    /// Parses a `let $pat = $expr` pseudo-expression.
     /// The `let` token has already been eaten.
     fn parse_let_expr(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
         let lo = self.prev_span;
-        let pats = self.parse_pats()?;
+        // FIXME(or_patterns, Centril | dlrobertson): use `parse_top_pat` instead.
+        let pat = self.parse_top_pat_unpack(GateOr::No)?;
         self.expect(&token::Eq)?;
         let expr = self.with_res(
             Restrictions::NO_STRUCT_LITERAL,
@@ -1253,7 +1255,7 @@ impl<'a> Parser<'a> {
         )?;
         let span = lo.to(expr.span);
         self.sess.gated_spans.let_chains.borrow_mut().push(span);
-        Ok(self.mk_expr(span, ExprKind::Let(pats, expr), attrs))
+        Ok(self.mk_expr(span, ExprKind::Let(pat, expr), attrs))
     }
 
     /// `else` token already eaten
@@ -1283,7 +1285,7 @@ impl<'a> Parser<'a> {
             _ => None,
         };
 
-        let pat = self.parse_top_level_pat()?;
+        let pat = self.parse_top_pat(GateOr::Yes)?;
         if !self.eat_keyword(kw::In) {
             let in_span = self.prev_span.between(self.token.span);
             self.struct_span_err(in_span, "missing `in` in `for` loop")
@@ -1387,7 +1389,8 @@ impl<'a> Parser<'a> {
     crate fn parse_arm(&mut self) -> PResult<'a, Arm> {
         let attrs = self.parse_outer_attributes()?;
         let lo = self.token.span;
-        let pats = self.parse_pats()?;
+        // FIXME(or_patterns, Centril | dlrobertson): use `parse_top_pat` instead.
+        let pat = self.parse_top_pat_unpack(GateOr::No)?;
         let guard = if self.eat_keyword(kw::If) {
             Some(self.parse_expr()?)
         } else {
@@ -1448,7 +1451,7 @@ impl<'a> Parser<'a> {
 
         Ok(ast::Arm {
             attrs,
-            pats,
+            pats: pat, // FIXME(or_patterns, Centril | dlrobertson): this should just be `pat,`.
             guard,
             body: expr,
             span: lo.to(hi),