Skip to content

Commit 71f20b8

Browse files
authored
Rollup merge of rust-lang#66718 - VirrageS:use_comma, r=Centril
Refactor `parse_enum_item` to use `parse_delim_comma_seq` Followup after rust-lang#66641 Some errors got more verbose but I think they make sense with the help message.
2 parents ddb616d + 5c34a11 commit 71f20b8

File tree

11 files changed

+124
-92
lines changed

11 files changed

+124
-92
lines changed

src/librustc_parse/parser/item.rs

+47-68
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use syntax::ast::{self, DUMMY_NODE_ID, Ident, Attribute, AttrKind, AttrStyle, An
77
use syntax::ast::{ItemKind, ImplItem, ImplItemKind, TraitItem, TraitItemKind, UseTree, UseTreeKind};
88
use syntax::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness, Extern, StrLit};
99
use syntax::ast::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem, ForeignItemKind};
10-
use syntax::ast::{Ty, TyKind, Generics, TraitRef, EnumDef, VariantData, StructField};
10+
use syntax::ast::{Ty, TyKind, Generics, TraitRef, EnumDef, Variant, VariantData, StructField};
1111
use syntax::ast::{Mac, MacDelimiter, Block, BindingMode, FnDecl, FnSig, SelfKind, Param};
1212
use syntax::print::pprust;
1313
use syntax::ptr::P;
@@ -1329,85 +1329,65 @@ impl<'a> Parser<'a> {
13291329
let id = self.parse_ident()?;
13301330
let mut generics = self.parse_generics()?;
13311331
generics.where_clause = self.parse_where_clause()?;
1332-
self.expect(&token::OpenDelim(token::Brace))?;
13331332

1334-
let enum_definition = self.parse_enum_def(&generics).map_err(|e| {
1333+
let (variants, _) = self.parse_delim_comma_seq(
1334+
token::Brace,
1335+
|p| p.parse_enum_item(),
1336+
).map_err(|e| {
13351337
self.recover_stmt();
1336-
self.eat(&token::CloseDelim(token::Brace));
13371338
e
13381339
})?;
1340+
1341+
let enum_definition = EnumDef {
1342+
variants: variants.into_iter().filter_map(|v| v).collect(),
1343+
};
13391344
Ok((id, ItemKind::Enum(enum_definition, generics), None))
13401345
}
13411346

1342-
/// Parses the part of an enum declaration following the `{`.
1343-
fn parse_enum_def(&mut self, _generics: &Generics) -> PResult<'a, EnumDef> {
1344-
let mut variants = Vec::new();
1345-
// FIXME: Consider using `parse_delim_comma_seq`.
1346-
// We could then remove eating comma in `recover_nested_adt_item`.
1347-
while self.token != token::CloseDelim(token::Brace) {
1348-
let variant_attrs = self.parse_outer_attributes()?;
1349-
let vlo = self.token.span;
1350-
1351-
let vis = self.parse_visibility(FollowedByType::No)?;
1352-
if !self.recover_nested_adt_item(kw::Enum)? {
1353-
// Item already parsed, we need to skip this variant.
1354-
continue
1355-
}
1356-
let ident = self.parse_ident()?;
1347+
fn parse_enum_item(&mut self) -> PResult<'a, Option<Variant>> {
1348+
let variant_attrs = self.parse_outer_attributes()?;
1349+
let vlo = self.token.span;
13571350

1358-
let struct_def = if self.check(&token::OpenDelim(token::Brace)) {
1359-
// Parse a struct variant.
1360-
let (fields, recovered) = self.parse_record_struct_body()?;
1361-
VariantData::Struct(fields, recovered)
1362-
} else if self.check(&token::OpenDelim(token::Paren)) {
1363-
VariantData::Tuple(
1364-
self.parse_tuple_struct_body()?,
1365-
DUMMY_NODE_ID,
1366-
)
1367-
} else {
1368-
VariantData::Unit(DUMMY_NODE_ID)
1369-
};
1351+
let vis = self.parse_visibility(FollowedByType::No)?;
1352+
if !self.recover_nested_adt_item(kw::Enum)? {
1353+
return Ok(None)
1354+
}
1355+
let ident = self.parse_ident()?;
13701356

1371-
let disr_expr = if self.eat(&token::Eq) {
1372-
Some(AnonConst {
1373-
id: DUMMY_NODE_ID,
1374-
value: self.parse_expr()?,
1375-
})
1376-
} else {
1377-
None
1378-
};
1357+
let struct_def = if self.check(&token::OpenDelim(token::Brace)) {
1358+
// Parse a struct variant.
1359+
let (fields, recovered) = self.parse_record_struct_body()?;
1360+
VariantData::Struct(fields, recovered)
1361+
} else if self.check(&token::OpenDelim(token::Paren)) {
1362+
VariantData::Tuple(
1363+
self.parse_tuple_struct_body()?,
1364+
DUMMY_NODE_ID,
1365+
)
1366+
} else {
1367+
VariantData::Unit(DUMMY_NODE_ID)
1368+
};
13791369

1380-
let vr = ast::Variant {
1381-
ident,
1382-
vis,
1370+
let disr_expr = if self.eat(&token::Eq) {
1371+
Some(AnonConst {
13831372
id: DUMMY_NODE_ID,
1384-
attrs: variant_attrs,
1385-
data: struct_def,
1386-
disr_expr,
1387-
span: vlo.to(self.prev_span),
1388-
is_placeholder: false,
1389-
};
1390-
variants.push(vr);
1373+
value: self.parse_expr()?,
1374+
})
1375+
} else {
1376+
None
1377+
};
13911378

1392-
if !self.eat(&token::Comma) {
1393-
if self.token.is_ident() && !self.token.is_reserved_ident() {
1394-
let sp = self.sess.source_map().next_point(self.prev_span);
1395-
self.struct_span_err(sp, "missing comma")
1396-
.span_suggestion_short(
1397-
sp,
1398-
"missing comma",
1399-
",".to_owned(),
1400-
Applicability::MaybeIncorrect,
1401-
)
1402-
.emit();
1403-
} else {
1404-
break;
1405-
}
1406-
}
1407-
}
1408-
self.expect(&token::CloseDelim(token::Brace))?;
1379+
let vr = ast::Variant {
1380+
ident,
1381+
vis,
1382+
id: DUMMY_NODE_ID,
1383+
attrs: variant_attrs,
1384+
data: struct_def,
1385+
disr_expr,
1386+
span: vlo.to(self.prev_span),
1387+
is_placeholder: false,
1388+
};
14091389

1410-
Ok(ast::EnumDef { variants })
1390+
Ok(Some(vr))
14111391
}
14121392

14131393
/// Parses `struct Foo { ... }`.
@@ -1764,7 +1744,6 @@ impl<'a> Parser<'a> {
17641744
let kw_token = self.token.clone();
17651745
let kw_str = pprust::token_to_string(&kw_token);
17661746
let item = self.parse_item()?;
1767-
self.eat(&token::Comma);
17681747

17691748
self.struct_span_err(
17701749
kw_token.span,

src/librustc_parse/parser/mod.rs

+20-2
Original file line numberDiff line numberDiff line change
@@ -805,21 +805,39 @@ impl<'a> Parser<'a> {
805805
recovered = true;
806806
break;
807807
}
808-
Err(mut e) => {
808+
Err(mut expect_err) => {
809+
let sp = self.sess.source_map().next_point(self.prev_span);
810+
let token_str = pprust::token_kind_to_string(t);
811+
809812
// Attempt to keep parsing if it was a similar separator.
810813
if let Some(ref tokens) = t.similar_tokens() {
811814
if tokens.contains(&self.token.kind) {
812815
self.bump();
813816
}
814817
}
815-
e.emit();
818+
816819
// Attempt to keep parsing if it was an omitted separator.
817820
match f(self) {
818821
Ok(t) => {
822+
// Parsed successfully, therefore most probably the code only
823+
// misses a separator.
824+
expect_err
825+
.span_suggestion_short(
826+
sp,
827+
&format!("missing `{}`", token_str),
828+
token_str,
829+
Applicability::MaybeIncorrect,
830+
)
831+
.emit();
832+
819833
v.push(t);
820834
continue;
821835
},
822836
Err(mut e) => {
837+
// Parsing failed, therefore it must be something more serious
838+
// than just a missing separator.
839+
expect_err.emit();
840+
823841
e.cancel();
824842
break;
825843
}

src/test/ui/on-unimplemented/expected-comma-found-token.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ error: expected one of `)` or `,`, found `label`
22
--> $DIR/expected-comma-found-token.rs:9:5
33
|
44
LL | message="the message"
5-
| - expected one of `)` or `,`
5+
| -
6+
| |
7+
| expected one of `)` or `,`
8+
| help: missing `,`
69
LL | label="the label"
710
| ^^^^^ unexpected token
811

src/test/ui/parser/pat-lt-bracket-6.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ error: expected one of `)`, `,`, `@`, or `|`, found `[`
22
--> $DIR/pat-lt-bracket-6.rs:5:19
33
|
44
LL | let Test(&desc[..]) = x;
5-
| ^ expected one of `)`, `,`, `@`, or `|`
5+
| ^
6+
| |
7+
| expected one of `)`, `,`, `@`, or `|`
8+
| help: missing `,`
69

710
error[E0658]: subslice patterns are unstable
811
--> $DIR/pat-lt-bracket-6.rs:5:20

src/test/ui/parser/pat-lt-bracket-7.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ error: expected one of `)`, `,`, `@`, or `|`, found `[`
22
--> $DIR/pat-lt-bracket-7.rs:5:16
33
|
44
LL | for Thing(x[]) in foo {}
5-
| ^ expected one of `)`, `,`, `@`, or `|`
5+
| ^
6+
| |
7+
| expected one of `)`, `,`, `@`, or `|`
8+
| help: missing `,`
69

710
error[E0308]: mismatched types
811
--> $DIR/pat-lt-bracket-7.rs:9:30

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

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

7-
error: missing comma
8-
--> $DIR/recover-enum.rs:5:19
12+
error: expected one of `,`, `=`, or `}`, found `Stuff`
13+
--> $DIR/recover-enum.rs:6:9
914
|
1015
LL | Bad(usize)
11-
| ^ help: missing comma
16+
| -
17+
| |
18+
| expected one of `,`, `=`, or `}`
19+
| help: missing `,`
20+
LL |
21+
LL | Stuff { a: usize }
22+
| ^^^^^ unexpected token
1223

13-
error: missing comma
14-
--> $DIR/recover-enum.rs:7:27
24+
error: expected one of `,`, `=`, or `}`, found `Here`
25+
--> $DIR/recover-enum.rs:8:9
1526
|
1627
LL | Stuff { a: usize }
17-
| ^ help: missing comma
28+
| -
29+
| |
30+
| expected one of `,`, `=`, or `}`
31+
| help: missing `,`
32+
LL |
33+
LL | Here
34+
| ^^^^ unexpected token
1835

1936
error: aborting due to 3 previous errors
2037

src/test/ui/similar-tokens.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ error: expected one of `,`, `::`, `as`, or `}`, found `.`
22
--> $DIR/similar-tokens.rs:7:10
33
|
44
LL | use x::{A. B};
5-
| ^ expected one of `,`, `::`, `as`, or `}`
5+
| ^
6+
| |
7+
| expected one of `,`, `::`, `as`, or `}`
8+
| help: missing `,`
69

710
error: aborting due to previous error
811

src/test/ui/tuple/tuple-struct-fields/test.stderr

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ error: expected one of `)` or `,`, found `(`
22
--> $DIR/test.rs:4:26
33
|
44
LL | struct S2(pub((foo)) ());
5-
| ^ expected one of `)` or `,`
5+
| -^ expected one of `)` or `,`
6+
| |
7+
| help: missing `,`
68

79
error[E0412]: cannot find type `foo` in this scope
810
--> $DIR/test.rs:4:20

src/test/ui/tuple/tuple-struct-fields/test2.stderr

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ error: expected one of `)` or `,`, found `(`
22
--> $DIR/test2.rs:5:26
33
|
44
LL | struct S3(pub $t ());
5-
| ^ expected one of `)` or `,`
5+
| -^ expected one of `)` or `,`
6+
| |
7+
| help: missing `,`
68
...
79
LL | define_struct! { (foo) }
810
| ------------------------ in this macro invocation

src/test/ui/tuple/tuple-struct-fields/test3.stderr

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ error: expected one of `)` or `,`, found `(`
22
--> $DIR/test3.rs:5:27
33
|
44
LL | struct S3(pub($t) ());
5-
| ^ expected one of `)` or `,`
5+
| -^ expected one of `)` or `,`
6+
| |
7+
| help: missing `,`
68
...
79
LL | define_struct! { foo }
810
| ---------------------- in this macro invocation

0 commit comments

Comments
 (0)