Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recover from missing comma between enum variants and from bad pub kw #59031

Merged
merged 4 commits into from
Mar 22, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 33 additions & 3 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -7680,6 +7680,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.
Expand Down Expand Up @@ -7711,11 +7712,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",
);
Expand Down Expand Up @@ -8600,6 +8615,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) {
Expand Down
13 changes: 7 additions & 6 deletions src/test/ui/issues/issue-28433.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
// compile-flags: -Z continue-parse-after-error

enum bird {
pub duck,
//~^ ERROR: expected identifier, found keyword `pub`
//~| ERROR: expected
goose
enum Bird {
pub Duck,
//~^ ERROR unnecessary visibility qualifier
Goose,
pub(crate) Dove
//~^ ERROR unnecessary visibility qualifier
}


fn main() {
let y = bird::goose;
let y = Bird::Goose;
}
18 changes: 7 additions & 11 deletions src/test/ui/issues/issue-28433.stderr
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
error: expected identifier, found keyword `pub`
error: unnecessary visibility qualifier
--> $DIR/issue-28433.rs:4:5
|
LL | pub duck,
| ^^^ expected identifier, found keyword
help: you can escape reserved keywords to use them as identifiers
|
LL | r#pub duck,
| ^^^^^
LL | pub Duck,
| ^^^ `pub` not permitted here

error: expected one of `(`, `,`, `=`, `{`, or `}`, found `duck`
--> $DIR/issue-28433.rs:4:9
error: unnecessary visibility qualifier
--> $DIR/issue-28433.rs:7:5
|
LL | pub duck,
| ^^^^ expected one of `(`, `,`, `=`, `{`, or `}` here
LL | pub(crate) Dove
| ^^^^^^^^^^ `pub` not permitted here

error: aborting due to 2 previous errors

8 changes: 6 additions & 2 deletions src/test/ui/parser/recover-enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,11 @@
fn main() {
enum Test {
Very
Bad //~ ERROR found `Bad`
Stuff
//~^ ERROR missing comma
Bad(usize)
//~^ ERROR missing comma
Stuff { a: usize }
//~^ ERROR missing comma
Here
}
}
22 changes: 16 additions & 6 deletions src/test/ui/parser/recover-enum.stderr
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
error: expected one of `(`, `,`, `=`, `{`, or `}`, found `Bad`
--> $DIR/recover-enum.rs:6:9
error: missing comma
--> $DIR/recover-enum.rs:5:13
|
LL | Very
| - expected one of `(`, `,`, `=`, `{`, or `}` here
LL | Bad
| ^^^ unexpected token
| ^ help: missing comma

error: aborting due to previous error
error: missing comma
--> $DIR/recover-enum.rs:7:19
|
LL | Bad(usize)
| ^ help: missing comma

error: missing comma
--> $DIR/recover-enum.rs:9:27
|
LL | Stuff { a: usize }
| ^ help: missing comma

error: aborting due to 3 previous errors

2 changes: 1 addition & 1 deletion src/test/ui/parser/trait-pub-assoc-const.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
trait Foo {
pub const Foo: u32;
//~^ ERROR expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found
//~^ ERROR unnecessary visibility qualifier
}

fn main() {}
6 changes: 2 additions & 4 deletions src/test/ui/parser/trait-pub-assoc-const.stderr
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
error: expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found `pub`
error: unnecessary visibility qualifier
--> $DIR/trait-pub-assoc-const.rs:2:5
|
LL | trait Foo {
| - expected one of 7 possible tokens here
LL | pub const Foo: u32;
| ^^^ unexpected token
| ^^^ `pub` not permitted here

error: aborting due to previous error

2 changes: 1 addition & 1 deletion src/test/ui/parser/trait-pub-assoc-ty.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
trait Foo {
pub type Foo;
//~^ ERROR expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found
//~^ ERROR unnecessary visibility qualifier
}

fn main() {}
6 changes: 2 additions & 4 deletions src/test/ui/parser/trait-pub-assoc-ty.stderr
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
error: expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found `pub`
error: unnecessary visibility qualifier
--> $DIR/trait-pub-assoc-ty.rs:2:5
|
LL | trait Foo {
| - expected one of 7 possible tokens here
LL | pub type Foo;
| ^^^ unexpected token
| ^^^ `pub` not permitted here

error: aborting due to previous error

2 changes: 1 addition & 1 deletion src/test/ui/parser/trait-pub-method.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
trait Foo {
pub fn foo();
//~^ ERROR expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found
//~^ ERROR unnecessary visibility qualifier
}

fn main() {}
6 changes: 2 additions & 4 deletions src/test/ui/parser/trait-pub-method.stderr
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
error: expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found `pub`
error: unnecessary visibility qualifier
--> $DIR/trait-pub-method.rs:2:5
|
LL | trait Foo {
| - expected one of 7 possible tokens here
LL | pub fn foo();
| ^^^ unexpected token
| ^^^ `pub` not permitted here

error: aborting due to previous error