Skip to content

Commit a85ec7c

Browse files
committed
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.
2 parents 86466a3 + 0a09e76 commit a85ec7c

11 files changed

+78
-43
lines changed

src/libsyntax/parse/parser.rs

+33-3
Original file line numberDiff line numberDiff line change
@@ -1524,7 +1524,7 @@ impl<'a> Parser<'a> {
15241524
at_end: &mut bool,
15251525
mut attrs: Vec<Attribute>) -> PResult<'a, TraitItem> {
15261526
let lo = self.span;
1527-
1527+
self.eat_bad_pub();
15281528
let (name, node, generics) = if self.eat_keyword(keywords::Type) {
15291529
self.parse_trait_item_assoc_ty()?
15301530
} else if self.is_const_item() {
@@ -7688,6 +7688,7 @@ impl<'a> Parser<'a> {
76887688

76897689
let struct_def;
76907690
let mut disr_expr = None;
7691+
self.eat_bad_pub();
76917692
let ident = self.parse_ident()?;
76927693
if self.check(&token::OpenDelim(token::Brace)) {
76937694
// Parse a struct variant.
@@ -7719,11 +7720,25 @@ impl<'a> Parser<'a> {
77197720
};
77207721
variants.push(respan(vlo.to(self.prev_span), vr));
77217722

7722-
if !self.eat(&token::Comma) { break; }
7723+
if !self.eat(&token::Comma) {
7724+
if self.token.is_ident() && !self.token.is_reserved_ident() {
7725+
let sp = self.sess.source_map().next_point(self.prev_span);
7726+
let mut err = self.struct_span_err(sp, "missing comma");
7727+
err.span_suggestion_short(
7728+
sp,
7729+
"missing comma",
7730+
",".to_owned(),
7731+
Applicability::MaybeIncorrect,
7732+
);
7733+
err.emit();
7734+
} else {
7735+
break;
7736+
}
7737+
}
77237738
}
77247739
self.expect(&token::CloseDelim(token::Brace))?;
77257740
if !any_disr.is_empty() && !all_nullary {
7726-
let mut err =self.struct_span_err(
7741+
let mut err = self.struct_span_err(
77277742
any_disr.clone(),
77287743
"discriminator values can only be used with a field-less enum",
77297744
);
@@ -8608,6 +8623,21 @@ impl<'a> Parser<'a> {
86088623
Applicability::MaybeIncorrect,
86098624
).emit();
86108625
}
8626+
8627+
/// Recover from `pub` keyword in places where it seems _reasonable_ but isn't valid.
8628+
fn eat_bad_pub(&mut self) {
8629+
if self.token.is_keyword(keywords::Pub) {
8630+
match self.parse_visibility(false) {
8631+
Ok(vis) => {
8632+
let mut err = self.diagnostic()
8633+
.struct_span_err(vis.span, "unnecessary visibility qualifier");
8634+
err.span_label(vis.span, "`pub` not permitted here");
8635+
err.emit();
8636+
}
8637+
Err(mut err) => err.emit(),
8638+
}
8639+
}
8640+
}
86118641
}
86128642

86138643
pub fn emit_unclosed_delims(unclosed_delims: &mut Vec<UnmatchedBrace>, handler: &errors::Handler) {

src/test/ui/issues/issue-28433.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
// compile-flags: -Z continue-parse-after-error
22

3-
enum bird {
4-
pub duck,
5-
//~^ ERROR: expected identifier, found keyword `pub`
6-
//~| ERROR: expected
7-
goose
3+
enum Bird {
4+
pub Duck,
5+
//~^ ERROR unnecessary visibility qualifier
6+
Goose,
7+
pub(crate) Dove
8+
//~^ ERROR unnecessary visibility qualifier
89
}
910

1011

1112
fn main() {
12-
let y = bird::goose;
13+
let y = Bird::Goose;
1314
}

src/test/ui/issues/issue-28433.stderr

+7-11
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,14 @@
1-
error: expected identifier, found keyword `pub`
1+
error: unnecessary visibility qualifier
22
--> $DIR/issue-28433.rs:4:5
33
|
4-
LL | pub duck,
5-
| ^^^ expected identifier, found keyword
6-
help: you can escape reserved keywords to use them as identifiers
7-
|
8-
LL | r#pub duck,
9-
| ^^^^^
4+
LL | pub Duck,
5+
| ^^^ `pub` not permitted here
106

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

1713
error: aborting due to 2 previous errors
1814

src/test/ui/parser/recover-enum.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33
fn main() {
44
enum Test {
55
Very
6-
Bad //~ ERROR found `Bad`
7-
Stuff
6+
//~^ ERROR missing comma
7+
Bad(usize)
8+
//~^ ERROR missing comma
9+
Stuff { a: usize }
10+
//~^ ERROR missing comma
11+
Here
812
}
913
}
+16-6
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,20 @@
1-
error: expected one of `(`, `,`, `=`, `{`, or `}`, found `Bad`
2-
--> $DIR/recover-enum.rs:6:9
1+
error: missing comma
2+
--> $DIR/recover-enum.rs:5:13
33
|
44
LL | Very
5-
| - expected one of `(`, `,`, `=`, `{`, or `}` here
6-
LL | Bad
7-
| ^^^ unexpected token
5+
| ^ help: missing comma
86

9-
error: aborting due to previous error
7+
error: missing comma
8+
--> $DIR/recover-enum.rs:7:19
9+
|
10+
LL | Bad(usize)
11+
| ^ help: missing comma
12+
13+
error: missing comma
14+
--> $DIR/recover-enum.rs:9:27
15+
|
16+
LL | Stuff { a: usize }
17+
| ^ help: missing comma
18+
19+
error: aborting due to 3 previous errors
1020

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
trait Foo {
22
pub const Foo: u32;
3-
//~^ ERROR expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found
3+
//~^ ERROR unnecessary visibility qualifier
44
}
55

66
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1-
error: expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found `pub`
1+
error: unnecessary visibility qualifier
22
--> $DIR/trait-pub-assoc-const.rs:2:5
33
|
4-
LL | trait Foo {
5-
| - expected one of 7 possible tokens here
64
LL | pub const Foo: u32;
7-
| ^^^ unexpected token
5+
| ^^^ `pub` not permitted here
86

97
error: aborting due to previous error
108

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
trait Foo {
22
pub type Foo;
3-
//~^ ERROR expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found
3+
//~^ ERROR unnecessary visibility qualifier
44
}
55

66
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1-
error: expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found `pub`
1+
error: unnecessary visibility qualifier
22
--> $DIR/trait-pub-assoc-ty.rs:2:5
33
|
4-
LL | trait Foo {
5-
| - expected one of 7 possible tokens here
64
LL | pub type Foo;
7-
| ^^^ unexpected token
5+
| ^^^ `pub` not permitted here
86

97
error: aborting due to previous error
108

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
trait Foo {
22
pub fn foo();
3-
//~^ ERROR expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found
3+
//~^ ERROR unnecessary visibility qualifier
44
}
55

66
fn main() {}
+2-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1-
error: expected one of `async`, `const`, `extern`, `fn`, `type`, `unsafe`, or `}`, found `pub`
1+
error: unnecessary visibility qualifier
22
--> $DIR/trait-pub-method.rs:2:5
33
|
4-
LL | trait Foo {
5-
| - expected one of 7 possible tokens here
64
LL | pub fn foo();
7-
| ^^^ unexpected token
5+
| ^^^ `pub` not permitted here
86

97
error: aborting due to previous error
108

0 commit comments

Comments
 (0)