Skip to content

Commit 6717f81

Browse files
Also take unions and enums into account
1 parent 1e642f0 commit 6717f81

File tree

3 files changed

+61
-19
lines changed

3 files changed

+61
-19
lines changed

compiler/rustc_parse/src/parser/item.rs

+19-14
Original file line numberDiff line numberDiff line change
@@ -1124,11 +1124,11 @@ impl<'a> Parser<'a> {
11241124
if !this.recover_nested_adt_item(kw::Enum)? {
11251125
return Ok((None, TrailingToken::None));
11261126
}
1127-
let ident = this.parse_ident()?;
1127+
let ident = this.parse_field_ident("enum", vlo)?;
11281128

11291129
let struct_def = if this.check(&token::OpenDelim(token::Brace)) {
11301130
// Parse a struct variant.
1131-
let (fields, recovered) = this.parse_record_struct_body()?;
1131+
let (fields, recovered) = this.parse_record_struct_body("struct")?;
11321132
VariantData::Struct(fields, recovered)
11331133
} else if this.check(&token::OpenDelim(token::Paren)) {
11341134
VariantData::Tuple(this.parse_tuple_struct_body()?, DUMMY_NODE_ID)
@@ -1182,15 +1182,15 @@ impl<'a> Parser<'a> {
11821182
VariantData::Unit(DUMMY_NODE_ID)
11831183
} else {
11841184
// If we see: `struct Foo<T> where T: Copy { ... }`
1185-
let (fields, recovered) = self.parse_record_struct_body()?;
1185+
let (fields, recovered) = self.parse_record_struct_body("struct")?;
11861186
VariantData::Struct(fields, recovered)
11871187
}
11881188
// No `where` so: `struct Foo<T>;`
11891189
} else if self.eat(&token::Semi) {
11901190
VariantData::Unit(DUMMY_NODE_ID)
11911191
// Record-style struct definition
11921192
} else if self.token == token::OpenDelim(token::Brace) {
1193-
let (fields, recovered) = self.parse_record_struct_body()?;
1193+
let (fields, recovered) = self.parse_record_struct_body("struct")?;
11941194
VariantData::Struct(fields, recovered)
11951195
// Tuple-style struct definition with optional where-clause.
11961196
} else if self.token == token::OpenDelim(token::Paren) {
@@ -1220,10 +1220,10 @@ impl<'a> Parser<'a> {
12201220

12211221
let vdata = if self.token.is_keyword(kw::Where) {
12221222
generics.where_clause = self.parse_where_clause()?;
1223-
let (fields, recovered) = self.parse_record_struct_body()?;
1223+
let (fields, recovered) = self.parse_record_struct_body("union")?;
12241224
VariantData::Struct(fields, recovered)
12251225
} else if self.token == token::OpenDelim(token::Brace) {
1226-
let (fields, recovered) = self.parse_record_struct_body()?;
1226+
let (fields, recovered) = self.parse_record_struct_body("union")?;
12271227
VariantData::Struct(fields, recovered)
12281228
} else {
12291229
let token_str = super::token_descr(&self.token);
@@ -1236,12 +1236,15 @@ impl<'a> Parser<'a> {
12361236
Ok((class_name, ItemKind::Union(vdata, generics)))
12371237
}
12381238

1239-
fn parse_record_struct_body(&mut self) -> PResult<'a, (Vec<FieldDef>, /* recovered */ bool)> {
1239+
fn parse_record_struct_body(
1240+
&mut self,
1241+
adt_ty: &str,
1242+
) -> PResult<'a, (Vec<FieldDef>, /* recovered */ bool)> {
12401243
let mut fields = Vec::new();
12411244
let mut recovered = false;
12421245
if self.eat(&token::OpenDelim(token::Brace)) {
12431246
while self.token != token::CloseDelim(token::Brace) {
1244-
let field = self.parse_field_def().map_err(|e| {
1247+
let field = self.parse_field_def(adt_ty).map_err(|e| {
12451248
self.consume_block(token::Brace, ConsumeClosingDelim::No);
12461249
recovered = true;
12471250
e
@@ -1294,24 +1297,25 @@ impl<'a> Parser<'a> {
12941297
}
12951298

12961299
/// Parses an element of a struct declaration.
1297-
fn parse_field_def(&mut self) -> PResult<'a, FieldDef> {
1300+
fn parse_field_def(&mut self, adt_ty: &str) -> PResult<'a, FieldDef> {
12981301
let attrs = self.parse_outer_attributes()?;
12991302
self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
13001303
let lo = this.token.span;
13011304
let vis = this.parse_visibility(FollowedByType::No)?;
1302-
Ok((this.parse_single_struct_field(lo, vis, attrs)?, TrailingToken::None))
1305+
Ok((this.parse_single_struct_field(adt_ty, lo, vis, attrs)?, TrailingToken::None))
13031306
})
13041307
}
13051308

13061309
/// Parses a structure field declaration.
13071310
fn parse_single_struct_field(
13081311
&mut self,
1312+
adt_ty: &str,
13091313
lo: Span,
13101314
vis: Visibility,
13111315
attrs: Vec<Attribute>,
13121316
) -> PResult<'a, FieldDef> {
13131317
let mut seen_comma: bool = false;
1314-
let a_var = self.parse_name_and_ty(lo, vis, attrs)?;
1318+
let a_var = self.parse_name_and_ty(adt_ty, lo, vis, attrs)?;
13151319
if self.token == token::Comma {
13161320
seen_comma = true;
13171321
}
@@ -1398,11 +1402,12 @@ impl<'a> Parser<'a> {
13981402
/// Parses a structure field.
13991403
fn parse_name_and_ty(
14001404
&mut self,
1405+
adt_ty: &str,
14011406
lo: Span,
14021407
vis: Visibility,
14031408
attrs: Vec<Attribute>,
14041409
) -> PResult<'a, FieldDef> {
1405-
let name = self.parse_field_ident(lo)?;
1410+
let name = self.parse_field_ident(adt_ty, lo)?;
14061411
self.expect(&token::Colon)?;
14071412
let ty = self.parse_ty()?;
14081413
Ok(FieldDef {
@@ -1418,14 +1423,14 @@ impl<'a> Parser<'a> {
14181423

14191424
/// Parses a field identifier. Specialized version of `parse_ident_common`
14201425
/// for better diagnostics and suggestions.
1421-
fn parse_field_ident(&mut self, lo: Span) -> PResult<'a, Ident> {
1426+
fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> {
14221427
let (ident, is_raw) = self.ident_or_err()?;
14231428
if !is_raw && ident.is_reserved() {
14241429
let err = if self.check_fn_front_matter(false) {
14251430
let _ = self.parse_fn(&mut Vec::new(), |_| true, lo);
14261431
let mut err = self.struct_span_err(
14271432
lo.to(self.prev_token.span),
1428-
"functions are not allowed in struct definitions",
1433+
&format!("functions are not allowed in {} definitions", adt_ty),
14291434
);
14301435
err.help("unlike in C++, Java, and C#, functions are declared in `impl` blocks");
14311436
err.help("see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information");

src/test/ui/structs/struct-fn-in-definition.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,29 @@
55

66
struct S {
77
field: usize,
8-
fn do_something() {}
8+
9+
fn foo() {}
910
//~^ ERROR functions are not allowed in struct definitions
1011
//~| HELP unlike in C++, Java, and C#, functions are declared in `impl` blocks
1112
//~| HELP see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information
1213
}
1314

15+
union U {
16+
variant: usize,
17+
18+
fn foo() {}
19+
//~^ ERROR functions are not allowed in union definitions
20+
//~| HELP unlike in C++, Java, and C#, functions are declared in `impl` blocks
21+
//~| HELP see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information
22+
}
23+
24+
enum E {
25+
Variant,
26+
27+
fn foo() {}
28+
//~^ ERROR functions are not allowed in enum definitions
29+
//~| HELP unlike in C++, Java, and C#, functions are declared in `impl` blocks
30+
//~| HELP see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information
31+
}
32+
1433
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,29 @@
11
error: functions are not allowed in struct definitions
2-
--> $DIR/struct-fn-in-definition.rs:5:5
2+
--> $DIR/struct-fn-in-definition.rs:9:5
33
|
4-
LL | fn do_something() {}
5-
| ^^^^^^^^^^^^^^^^^^^^
4+
LL | fn foo() {}
5+
| ^^^^^^^^^^^
66
|
77
= help: unlike in C++, Java, and C#, functions are declared in `impl` blocks
88
= help: see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information
99

10-
error: aborting due to previous error
10+
error: functions are not allowed in union definitions
11+
--> $DIR/struct-fn-in-definition.rs:18:5
12+
|
13+
LL | fn foo() {}
14+
| ^^^^^^^^^^^
15+
|
16+
= help: unlike in C++, Java, and C#, functions are declared in `impl` blocks
17+
= help: see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information
18+
19+
error: functions are not allowed in enum definitions
20+
--> $DIR/struct-fn-in-definition.rs:27:5
21+
|
22+
LL | fn foo() {}
23+
| ^^^^^^^^^^^
24+
|
25+
= help: unlike in C++, Java, and C#, functions are declared in `impl` blocks
26+
= help: see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information
27+
28+
error: aborting due to 3 previous errors
1129

0 commit comments

Comments
 (0)