about summary refs log tree commit diff
path: root/src/libsyntax/parse
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-03-22 21:00:07 +0000
committerbors <bors@rust-lang.org>2019-03-22 21:00:07 +0000
commit9f91bee03f3eea93285330354dda54706028671c (patch)
tree0b8cb0de7ea1416081cfa16e36ea400a9d966498 /src/libsyntax/parse
parentcb2f34dc6d7e83d8bcfef79e0388d49f0c24aca7 (diff)
parentcf8c73936d48560b50d98a299c98fd35e5b4581e (diff)
downloadrust-9f91bee03f3eea93285330354dda54706028671c.tar.gz
rust-9f91bee03f3eea93285330354dda54706028671c.zip
Auto merge of #59370 - Centril:rollup, r=Centril
Rollup of 18 pull requests

Successful merges:

 - #59106 (Add peer_addr function to UdpSocket)
 - #59170 (Add const generics to rustdoc)
 - #59172 (Update and clean up several parts of CONTRIBUTING.md)
 - #59190 (consistent naming for Rhs type parameter in libcore/ops)
 - #59236 (Rename miri component to miri-preview)
 - #59266 (Do not complain about non-existing fields after parse recovery)
 - #59273 (some small HIR doc improvements)
 - #59291 (Make Option<ThreadId> no larger than ThreadId, with NonZeroU64)
 - #59297 (convert field/method confusion help to suggestions)
 - #59304 (Move some bench tests back from libtest)
 - #59309 (Add messages for different verbosity levels. Output copy actions.)
 - #59321 (Unify E0109, E0110 and E0111)
 - #59322 (Tweak incorrect escaped char diagnostic)
 - #59323 (use suggestions for "enum instead of variant" error)
 - #59327 (Add NAN test to docs)
 - #59329 (cleanup: Remove compile-fail-fulldeps directory again)
 - #59347 (Move one test from run-make-fulldeps to ui)
 - #59360 (Add tracking issue number for `seek_convenience`)

Failed merges:

r? @ghost
Diffstat (limited to 'src/libsyntax/parse')
-rw-r--r--src/libsyntax/parse/lexer/mod.rs38
-rw-r--r--src/libsyntax/parse/parser.rs43
2 files changed, 48 insertions, 33 deletions
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs
index bcd53dbfeb2..cd4944deadb 100644
--- a/src/libsyntax/parse/lexer/mod.rs
+++ b/src/libsyntax/parse/lexer/mod.rs
@@ -968,9 +968,10 @@ impl<'a> StringReader<'a> {
                                 } else {
                                     let span = self.mk_sp(start, self.pos);
                                     let mut suggestion = "\\u{".to_owned();
+                                    let msg = "incorrect unicode escape sequence";
                                     let mut err = self.sess.span_diagnostic.struct_span_err(
                                         span,
-                                        "incorrect unicode escape sequence",
+                                        msg,
                                     );
                                     let mut i = 0;
                                     while let (Some(ch), true) = (self.ch, i < 6) {
@@ -991,8 +992,8 @@ impl<'a> StringReader<'a> {
                                             Applicability::MaybeIncorrect,
                                         );
                                     } else {
-                                        err.span_help(
-                                            span,
+                                        err.span_label(span, msg);
+                                        err.help(
                                             "format of unicode escape sequences is `\\u{...}`",
                                         );
                                     }
@@ -1018,25 +1019,24 @@ impl<'a> StringReader<'a> {
                             }
                             c => {
                                 let pos = self.pos;
-                                let mut err = self.struct_err_span_char(escaped_pos,
-                                                                        pos,
-                                                                        if ascii_only {
-                                                                            "unknown byte escape"
-                                                                        } else {
-                                                                            "unknown character \
-                                                                             escape"
-                                                                        },
-                                                                        c);
+                                let msg = if ascii_only {
+                                    "unknown byte escape"
+                                } else {
+                                    "unknown character escape"
+                                };
+                                let mut err = self.struct_err_span_char(escaped_pos, pos, msg, c);
+                                err.span_label(self.mk_sp(escaped_pos, pos), msg);
                                 if e == '\r' {
-                                    err.span_help(self.mk_sp(escaped_pos, pos),
-                                                  "this is an isolated carriage return; consider \
-                                                   checking your editor and version control \
-                                                   settings");
+                                    err.help(
+                                        "this is an isolated carriage return; consider checking \
+                                         your editor and version control settings",
+                                    );
                                 }
                                 if (e == '{' || e == '}') && !ascii_only {
-                                    err.span_help(self.mk_sp(escaped_pos, pos),
-                                                  "if used in a formatting string, curly braces \
-                                                   are escaped with `{{` and `}}`");
+                                    err.help(
+                                        "if used in a formatting string, curly braces are escaped \
+                                         with `{{` and `}}`",
+                                    );
                                 }
                                 err.emit();
                                 false
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 7a4a687f90e..5627ac3fcf2 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -4229,19 +4229,24 @@ impl<'a> Parser<'a> {
     fn parse_pat_list(&mut self) -> PResult<'a, (Vec<P<Pat>>, Option<usize>, bool)> {
         let mut fields = Vec::new();
         let mut ddpos = None;
+        let mut prev_dd_sp = None;
         let mut trailing_comma = false;
         loop {
             if self.eat(&token::DotDot) {
                 if ddpos.is_none() {
                     ddpos = Some(fields.len());
+                    prev_dd_sp = Some(self.prev_span);
                 } else {
                     // Emit a friendly error, ignore `..` and continue parsing
-                    self.struct_span_err(
+                    let mut err = self.struct_span_err(
                         self.prev_span,
                         "`..` can only be used once per tuple or tuple struct pattern",
-                    )
-                        .span_label(self.prev_span, "can only be used once per pattern")
-                        .emit();
+                    );
+                    err.span_label(self.prev_span, "can only be used once per pattern");
+                    if let Some(sp) = prev_dd_sp {
+                        err.span_label(sp, "previously present here");
+                    }
+                    err.emit();
                 }
             } else if !self.check(&token::CloseDelim(token::Paren)) {
                 fields.push(self.parse_pat(None)?);
@@ -6837,14 +6842,16 @@ impl<'a> Parser<'a> {
                 VariantData::Unit(ast::DUMMY_NODE_ID)
             } else {
                 // If we see: `struct Foo<T> where T: Copy { ... }`
-                VariantData::Struct(self.parse_record_struct_body()?, ast::DUMMY_NODE_ID)
+                let (fields, recovered) = self.parse_record_struct_body()?;
+                VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered)
             }
         // No `where` so: `struct Foo<T>;`
         } else if self.eat(&token::Semi) {
             VariantData::Unit(ast::DUMMY_NODE_ID)
         // Record-style struct definition
         } else if self.token == token::OpenDelim(token::Brace) {
-            VariantData::Struct(self.parse_record_struct_body()?, ast::DUMMY_NODE_ID)
+            let (fields, recovered) = self.parse_record_struct_body()?;
+            VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered)
         // Tuple-style struct definition with optional where-clause.
         } else if self.token == token::OpenDelim(token::Paren) {
             let body = VariantData::Tuple(self.parse_tuple_struct_body()?, ast::DUMMY_NODE_ID);
@@ -6872,9 +6879,11 @@ impl<'a> Parser<'a> {
 
         let vdata = if self.token.is_keyword(keywords::Where) {
             generics.where_clause = self.parse_where_clause()?;
-            VariantData::Struct(self.parse_record_struct_body()?, ast::DUMMY_NODE_ID)
+            let (fields, recovered) = self.parse_record_struct_body()?;
+            VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered)
         } else if self.token == token::OpenDelim(token::Brace) {
-            VariantData::Struct(self.parse_record_struct_body()?, ast::DUMMY_NODE_ID)
+            let (fields, recovered) = self.parse_record_struct_body()?;
+            VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered)
         } else {
             let token_str = self.this_token_descr();
             let mut err = self.fatal(&format!(
@@ -6906,12 +6915,16 @@ impl<'a> Parser<'a> {
         }
     }
 
-    fn parse_record_struct_body(&mut self) -> PResult<'a, Vec<StructField>> {
+    fn parse_record_struct_body(
+        &mut self,
+    ) -> PResult<'a, (Vec<StructField>, /* recovered */ bool)> {
         let mut fields = Vec::new();
+        let mut recovered = false;
         if self.eat(&token::OpenDelim(token::Brace)) {
             while self.token != token::CloseDelim(token::Brace) {
                 let field = self.parse_struct_decl_field().map_err(|e| {
                     self.recover_stmt();
+                    recovered = true;
                     e
                 });
                 match field {
@@ -6930,7 +6943,7 @@ impl<'a> Parser<'a> {
             return Err(err);
         }
 
-        Ok(fields)
+        Ok((fields, recovered))
     }
 
     fn parse_tuple_struct_body(&mut self) -> PResult<'a, Vec<StructField>> {
@@ -7693,12 +7706,14 @@ impl<'a> Parser<'a> {
             if self.check(&token::OpenDelim(token::Brace)) {
                 // Parse a struct variant.
                 all_nullary = false;
-                struct_def = VariantData::Struct(self.parse_record_struct_body()?,
-                                                 ast::DUMMY_NODE_ID);
+                let (fields, recovered) = self.parse_record_struct_body()?;
+                struct_def = VariantData::Struct(fields, ast::DUMMY_NODE_ID, recovered);
             } else if self.check(&token::OpenDelim(token::Paren)) {
                 all_nullary = false;
-                struct_def = VariantData::Tuple(self.parse_tuple_struct_body()?,
-                                                ast::DUMMY_NODE_ID);
+                struct_def = VariantData::Tuple(
+                    self.parse_tuple_struct_body()?,
+                    ast::DUMMY_NODE_ID,
+                );
             } else if self.eat(&token::Eq) {
                 disr_expr = Some(AnonConst {
                     id: ast::DUMMY_NODE_ID,