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 04:52:10 +0000
committerbors <bors@rust-lang.org>2019-03-22 04:52:10 +0000
commita85ec7c2c005c1c2f85050151706c6301720760a (patch)
tree41f2c043693b15238fadb7336cbcc97b8898ce1d /src/libsyntax/parse
parent86466a397a4e43115231b66cf7935c7390f1aed2 (diff)
parent0a09e76c967cfe0eb43ccdf1bddc715cd3b81f41 (diff)
downloadrust-a85ec7c2c005c1c2f85050151706c6301720760a.tar.gz
rust-a85ec7c2c005c1c2f85050151706c6301720760a.zip
Auto merge of #59031 - estebank:recover-from-comaless, r=petrochenkov
Recover from missing comma between enum variants and from bad `pub` kw

Fix #56579. Fix #56473.
Diffstat (limited to 'src/libsyntax/parse')
-rw-r--r--src/libsyntax/parse/parser.rs36
1 files changed, 33 insertions, 3 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 3e00d948c1a..7a4a687f90e 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -1524,7 +1524,7 @@ impl<'a> Parser<'a> {
                          at_end: &mut bool,
                          mut attrs: Vec<Attribute>) -> PResult<'a, TraitItem> {
         let lo = self.span;
-
+        self.eat_bad_pub();
         let (name, node, generics) = if self.eat_keyword(keywords::Type) {
             self.parse_trait_item_assoc_ty()?
         } else if self.is_const_item() {
@@ -7688,6 +7688,7 @@ impl<'a> Parser<'a> {
 
             let struct_def;
             let mut disr_expr = None;
+            self.eat_bad_pub();
             let ident = self.parse_ident()?;
             if self.check(&token::OpenDelim(token::Brace)) {
                 // Parse a struct variant.
@@ -7719,11 +7720,25 @@ impl<'a> Parser<'a> {
             };
             variants.push(respan(vlo.to(self.prev_span), vr));
 
-            if !self.eat(&token::Comma) { break; }
+            if !self.eat(&token::Comma) {
+                if self.token.is_ident() && !self.token.is_reserved_ident() {
+                    let sp = self.sess.source_map().next_point(self.prev_span);
+                    let mut err = self.struct_span_err(sp, "missing comma");
+                    err.span_suggestion_short(
+                        sp,
+                        "missing comma",
+                        ",".to_owned(),
+                        Applicability::MaybeIncorrect,
+                    );
+                    err.emit();
+                } else {
+                    break;
+                }
+            }
         }
         self.expect(&token::CloseDelim(token::Brace))?;
         if !any_disr.is_empty() && !all_nullary {
-            let mut err =self.struct_span_err(
+            let mut err = self.struct_span_err(
                 any_disr.clone(),
                 "discriminator values can only be used with a field-less enum",
             );
@@ -8608,6 +8623,21 @@ impl<'a> Parser<'a> {
             Applicability::MaybeIncorrect,
         ).emit();
     }
+
+    /// Recover from `pub` keyword in places where it seems _reasonable_ but isn't valid.
+    fn eat_bad_pub(&mut self) {
+        if self.token.is_keyword(keywords::Pub) {
+            match self.parse_visibility(false) {
+                Ok(vis) => {
+                    let mut err = self.diagnostic()
+                        .struct_span_err(vis.span, "unnecessary visibility qualifier");
+                    err.span_label(vis.span, "`pub` not permitted here");
+                    err.emit();
+                }
+                Err(mut err) => err.emit(),
+            }
+        }
+    }
 }
 
 pub fn emit_unclosed_delims(unclosed_delims: &mut Vec<UnmatchedBrace>, handler: &errors::Handler) {