@@ -1124,11 +1124,11 @@ impl<'a> Parser<'a> {
1124
1124
if !this. recover_nested_adt_item ( kw:: Enum ) ? {
1125
1125
return Ok ( ( None , TrailingToken :: None ) ) ;
1126
1126
}
1127
- let ident = this. parse_ident ( ) ?;
1127
+ let ident = this. parse_field_ident ( "enum" , vlo ) ?;
1128
1128
1129
1129
let struct_def = if this. check ( & token:: OpenDelim ( token:: Brace ) ) {
1130
1130
// Parse a struct variant.
1131
- let ( fields, recovered) = this. parse_record_struct_body ( ) ?;
1131
+ let ( fields, recovered) = this. parse_record_struct_body ( "struct" ) ?;
1132
1132
VariantData :: Struct ( fields, recovered)
1133
1133
} else if this. check ( & token:: OpenDelim ( token:: Paren ) ) {
1134
1134
VariantData :: Tuple ( this. parse_tuple_struct_body ( ) ?, DUMMY_NODE_ID )
@@ -1182,15 +1182,15 @@ impl<'a> Parser<'a> {
1182
1182
VariantData :: Unit ( DUMMY_NODE_ID )
1183
1183
} else {
1184
1184
// 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" ) ?;
1186
1186
VariantData :: Struct ( fields, recovered)
1187
1187
}
1188
1188
// No `where` so: `struct Foo<T>;`
1189
1189
} else if self . eat ( & token:: Semi ) {
1190
1190
VariantData :: Unit ( DUMMY_NODE_ID )
1191
1191
// Record-style struct definition
1192
1192
} 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" ) ?;
1194
1194
VariantData :: Struct ( fields, recovered)
1195
1195
// Tuple-style struct definition with optional where-clause.
1196
1196
} else if self . token == token:: OpenDelim ( token:: Paren ) {
@@ -1220,10 +1220,10 @@ impl<'a> Parser<'a> {
1220
1220
1221
1221
let vdata = if self . token . is_keyword ( kw:: Where ) {
1222
1222
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" ) ?;
1224
1224
VariantData :: Struct ( fields, recovered)
1225
1225
} 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" ) ?;
1227
1227
VariantData :: Struct ( fields, recovered)
1228
1228
} else {
1229
1229
let token_str = super :: token_descr ( & self . token ) ;
@@ -1236,12 +1236,15 @@ impl<'a> Parser<'a> {
1236
1236
Ok ( ( class_name, ItemKind :: Union ( vdata, generics) ) )
1237
1237
}
1238
1238
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 ) > {
1240
1243
let mut fields = Vec :: new ( ) ;
1241
1244
let mut recovered = false ;
1242
1245
if self . eat ( & token:: OpenDelim ( token:: Brace ) ) {
1243
1246
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| {
1245
1248
self . consume_block ( token:: Brace , ConsumeClosingDelim :: No ) ;
1246
1249
recovered = true ;
1247
1250
e
@@ -1294,24 +1297,25 @@ impl<'a> Parser<'a> {
1294
1297
}
1295
1298
1296
1299
/// 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 > {
1298
1301
let attrs = self . parse_outer_attributes ( ) ?;
1299
1302
self . collect_tokens_trailing_token ( attrs, ForceCollect :: No , |this, attrs| {
1300
1303
let lo = this. token . span ;
1301
1304
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 ) )
1303
1306
} )
1304
1307
}
1305
1308
1306
1309
/// Parses a structure field declaration.
1307
1310
fn parse_single_struct_field (
1308
1311
& mut self ,
1312
+ adt_ty : & str ,
1309
1313
lo : Span ,
1310
1314
vis : Visibility ,
1311
1315
attrs : Vec < Attribute > ,
1312
1316
) -> PResult < ' a , FieldDef > {
1313
1317
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) ?;
1315
1319
if self . token == token:: Comma {
1316
1320
seen_comma = true ;
1317
1321
}
@@ -1398,11 +1402,12 @@ impl<'a> Parser<'a> {
1398
1402
/// Parses a structure field.
1399
1403
fn parse_name_and_ty (
1400
1404
& mut self ,
1405
+ adt_ty : & str ,
1401
1406
lo : Span ,
1402
1407
vis : Visibility ,
1403
1408
attrs : Vec < Attribute > ,
1404
1409
) -> PResult < ' a , FieldDef > {
1405
- let name = self . parse_ident_common ( false ) ?;
1410
+ let name = self . parse_field_ident ( adt_ty , lo ) ?;
1406
1411
self . expect ( & token:: Colon ) ?;
1407
1412
let ty = self . parse_ty ( ) ?;
1408
1413
Ok ( FieldDef {
@@ -1416,6 +1421,29 @@ impl<'a> Parser<'a> {
1416
1421
} )
1417
1422
}
1418
1423
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
+
1419
1447
/// Parses a declarative macro 2.0 definition.
1420
1448
/// The `macro` keyword has already been parsed.
1421
1449
/// ```
0 commit comments