@@ -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_ident_common ( false ) ?;
1410+ let name = self . parse_field_ident ( adt_ty , lo ) ?;
14061411 self . expect ( & token:: Colon ) ?;
14071412 let ty = self . parse_ty ( ) ?;
14081413 Ok ( FieldDef {
@@ -1416,6 +1421,29 @@ impl<'a> Parser<'a> {
14161421 } )
14171422 }
14181423
1424+ /// Parses a field identifier. Specialized version of `parse_ident_common`
1425+ /// for better diagnostics and suggestions.
1426+ fn parse_field_ident ( & mut self , adt_ty : & str , lo : Span ) -> PResult < ' a , Ident > {
1427+ let ( ident, is_raw) = self . ident_or_err ( ) ?;
1428+ if !is_raw && ident. is_reserved ( ) {
1429+ let err = if self . check_fn_front_matter ( false ) {
1430+ let _ = self . parse_fn ( & mut Vec :: new ( ) , |_| true , lo) ;
1431+ let mut err = self . struct_span_err (
1432+ lo. to ( self . prev_token . span ) ,
1433+ & format ! ( "functions are not allowed in {} definitions" , adt_ty) ,
1434+ ) ;
1435+ err. help ( "unlike in C++, Java, and C#, functions are declared in `impl` blocks" ) ;
1436+ err. help ( "see https://doc.rust-lang.org/book/ch05-03-method-syntax.html for more information" ) ;
1437+ err
1438+ } else {
1439+ self . expected_ident_found ( )
1440+ } ;
1441+ return Err ( err) ;
1442+ }
1443+ self . bump ( ) ;
1444+ Ok ( ident)
1445+ }
1446+
14191447 /// Parses a declarative macro 2.0 definition.
14201448 /// The `macro` keyword has already been parsed.
14211449 /// ```
0 commit comments