]> git.lizzy.rs Git - rust.git/commitdiff
extract parse_pat_{tuple_}struct + recover_one_fewer_dotdot
authorMazdak Farrokhzad <twingoow@gmail.com>
Mon, 12 Aug 2019 10:27:43 +0000 (12:27 +0200)
committerMazdak Farrokhzad <twingoow@gmail.com>
Mon, 12 Aug 2019 10:50:44 +0000 (12:50 +0200)
src/libsyntax/parse/parser/pat.rs

index 49090a57f62a17a6c796380735aee2c7b17f07d8..53f4d0998c3e1b7df6f3e2a28ecd573c006de91b 100644 (file)
@@ -169,34 +169,8 @@ fn parse_pat_with_range_pat(
                     token::DotDotDot | token::DotDotEq | token::DotDot => {
                         self.parse_pat_range_starting_with_path(lo, qself, path)?
                     }
-                    token::OpenDelim(token::Brace) => {
-                        if qself.is_some() {
-                            let msg = "unexpected `{` after qualified path";
-                            let mut err = self.fatal(msg);
-                            err.span_label(self.token.span, msg);
-                            return Err(err);
-                        }
-                        // Parse struct pattern
-                        self.bump();
-                        let (fields, etc) = self.parse_pat_fields().unwrap_or_else(|mut e| {
-                            e.emit();
-                            self.recover_stmt();
-                            (vec![], true)
-                        });
-                        self.bump();
-                        PatKind::Struct(path, fields, etc)
-                    }
-                    token::OpenDelim(token::Paren) => {
-                        if qself.is_some() {
-                            let msg = "unexpected `(` after qualified path";
-                            let mut err = self.fatal(msg);
-                            err.span_label(self.token.span, msg);
-                            return Err(err);
-                        }
-                        // Parse tuple struct or enum pattern
-                        let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat(None))?;
-                        PatKind::TupleStruct(path, fields)
-                    }
+                    token::OpenDelim(token::Brace) => self.parse_pat_struct(qself, path)?,
+                    token::OpenDelim(token::Paren) => self.parse_pat_tuple_struct(qself, path)?,
                     _ => PatKind::Path(qself, path),
                 }
             } else {
@@ -481,6 +455,37 @@ fn parse_pat_ident(&mut self, binding_mode: BindingMode) -> PResult<'a, PatKind>
         Ok(PatKind::Ident(binding_mode, ident, sub))
     }
 
+    /// Parse a struct ("record") pattern (e.g. `Foo { ... }` or `Foo::Bar { ... }`).
+    fn parse_pat_struct(&mut self, qself: Option<QSelf>, path: Path) -> PResult<'a, PatKind> {
+        if qself.is_some() {
+            let msg = "unexpected `{` after qualified path";
+            let mut err = self.fatal(msg);
+            err.span_label(self.token.span, msg);
+            return Err(err);
+        }
+
+        self.bump();
+        let (fields, etc) = self.parse_pat_fields().unwrap_or_else(|mut e| {
+            e.emit();
+            self.recover_stmt();
+            (vec![], true)
+        });
+        self.bump();
+        Ok(PatKind::Struct(path, fields, etc))
+    }
+
+    /// Parse tuple struct or tuple variant pattern (e.g. `Foo(...)` or `Foo::Bar(...)`).
+    fn parse_pat_tuple_struct(&mut self, qself: Option<QSelf>, path: Path) -> PResult<'a, PatKind> {
+        if qself.is_some() {
+            let msg = "unexpected `(` after qualified path";
+            let mut err = self.fatal(msg);
+            err.span_label(self.token.span, msg);
+            return Err(err);
+        }
+        let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat(None))?;
+        Ok(PatKind::TupleStruct(path, fields))
+    }
+
     /// Parses the fields of a struct-like pattern.
     fn parse_pat_fields(&mut self) -> PResult<'a, (Vec<Spanned<FieldPat>>, bool)> {
         let mut fields = Vec::new();
@@ -515,17 +520,7 @@ fn parse_pat_fields(&mut self) -> PResult<'a, (Vec<Spanned<FieldPat>>, bool)> {
                 etc = true;
                 let mut etc_sp = self.token.span;
 
-                if self.token == token::DotDotDot { // Issue #46718
-                    // Accept `...` as if it were `..` to avoid further errors
-                    self.struct_span_err(self.token.span, "expected field pattern, found `...`")
-                        .span_suggestion(
-                            self.token.span,
-                            "to omit remaining fields, use one fewer `.`",
-                            "..".to_owned(),
-                            Applicability::MachineApplicable
-                        )
-                        .emit();
-                }
+                self.recover_one_fewer_dotdot();
                 self.bump();  // `..` || `...`
 
                 if self.token == token::CloseDelim(token::Brace) {
@@ -607,6 +602,23 @@ fn parse_pat_fields(&mut self) -> PResult<'a, (Vec<Spanned<FieldPat>>, bool)> {
         return Ok((fields, etc));
     }
 
+    /// Recover on `...` as if it were `..` to avoid further errors.
+    /// See issue #46718.
+    fn recover_one_fewer_dotdot(&self) {
+        if self.token != token::DotDotDot {
+            return;
+        }
+
+        self.struct_span_err(self.token.span, "expected field pattern, found `...`")
+            .span_suggestion(
+                self.token.span,
+                "to omit remaining fields, use one fewer `.`",
+                "..".to_owned(),
+                Applicability::MachineApplicable
+            )
+            .emit();
+    }
+
     fn parse_pat_field(
         &mut self,
         lo: Span,