@@ -273,11 +273,13 @@ impl<'a> Parser<'a> {
273273 // TYPE ITEM
274274 self . parse_type_alias ( def ( ) ) ?
275275 } else if self . eat_keyword ( kw:: Enum ) {
276+ let start_span = self . prev_token . span ;
276277 // ENUM ITEM
277- self . parse_item_enum ( ) ?
278+ self . parse_item_enum ( start_span ) ?
278279 } else if self . eat_keyword ( kw:: Struct ) {
280+ let start_span = self . prev_token . span ;
279281 // STRUCT ITEM
280- self . parse_item_struct ( ) ?
282+ self . parse_item_struct ( start_span ) ?
281283 } else if self . is_kw_followed_by_ident ( kw:: Union ) {
282284 // UNION ITEM
283285 self . bump ( ) ; // `union`
@@ -1199,13 +1201,14 @@ impl<'a> Parser<'a> {
11991201 }
12001202
12011203 /// Parses an enum declaration.
1202- fn parse_item_enum ( & mut self ) -> PResult < ' a , ItemInfo > {
1204+ fn parse_item_enum ( & mut self , start_span : Span ) -> PResult < ' a , ItemInfo > {
12031205 let id = self . parse_ident ( ) ?;
12041206 let mut generics = self . parse_generics ( ) ?;
12051207 generics. where_clause = self . parse_where_clause ( ) ?;
12061208
1207- let ( variants, _) =
1208- self . parse_delim_comma_seq ( token:: Brace , |p| p. parse_enum_variant ( ) ) . map_err ( |e| {
1209+ let ( variants, _) = self
1210+ . parse_delim_comma_seq ( token:: Brace , |p| p. parse_enum_variant ( start_span) )
1211+ . map_err ( |e| {
12091212 self . recover_stmt ( ) ;
12101213 e
12111214 } ) ?;
@@ -1214,7 +1217,7 @@ impl<'a> Parser<'a> {
12141217 Ok ( ( id, ItemKind :: Enum ( enum_definition, generics) ) )
12151218 }
12161219
1217- fn parse_enum_variant ( & mut self ) -> PResult < ' a , Option < Variant > > {
1220+ fn parse_enum_variant ( & mut self , start_span : Span ) -> PResult < ' a , Option < Variant > > {
12181221 let variant_attrs = self . parse_outer_attributes ( ) ?;
12191222 self . collect_tokens_trailing_token (
12201223 variant_attrs,
@@ -1226,11 +1229,36 @@ impl<'a> Parser<'a> {
12261229 if !this. recover_nested_adt_item ( kw:: Enum ) ? {
12271230 return Ok ( ( None , TrailingToken :: None ) ) ;
12281231 }
1232+ let enum_field_start_span = this. token . span ;
12291233 let ident = this. parse_field_ident ( "enum" , vlo) ?;
1234+ if this. token . kind == token:: Colon {
1235+ let snapshot = this. clone ( ) ;
1236+ this. bump ( ) ;
1237+ match this. parse_ty ( ) {
1238+ Ok ( _) => {
1239+ let mut err = this. struct_span_err (
1240+ enum_field_start_span. to ( this. prev_token . span ) ,
1241+ "the enum cannot have a struct field declaration" ,
1242+ ) ;
1243+ err. span_suggestion_verbose (
1244+ start_span,
1245+ "consider using `struct` instead of `enum`" ,
1246+ "struct" . to_string ( ) ,
1247+ Applicability :: MaybeIncorrect ,
1248+ ) ;
1249+ return Err ( err) ;
1250+ }
1251+ Err ( e) => {
1252+ e. cancel ( ) ;
1253+ * this = snapshot;
1254+ }
1255+ } ;
1256+ }
12301257
12311258 let struct_def = if this. check ( & token:: OpenDelim ( token:: Brace ) ) {
12321259 // Parse a struct variant.
1233- let ( fields, recovered) = this. parse_record_struct_body ( "struct" , false ) ?;
1260+ let ( fields, recovered) =
1261+ this. parse_record_struct_body ( "struct" , false , None ) ?;
12341262 VariantData :: Struct ( fields, recovered)
12351263 } else if this. check ( & token:: OpenDelim ( token:: Paren ) ) {
12361264 VariantData :: Tuple ( this. parse_tuple_struct_body ( ) ?, DUMMY_NODE_ID )
@@ -1258,7 +1286,7 @@ impl<'a> Parser<'a> {
12581286 }
12591287
12601288 /// Parses `struct Foo { ... }`.
1261- fn parse_item_struct ( & mut self ) -> PResult < ' a , ItemInfo > {
1289+ fn parse_item_struct ( & mut self , start_span : Span ) -> PResult < ' a , ItemInfo > {
12621290 let class_name = self . parse_ident ( ) ?;
12631291
12641292 let mut generics = self . parse_generics ( ) ?;
@@ -1284,17 +1312,23 @@ impl<'a> Parser<'a> {
12841312 VariantData :: Unit ( DUMMY_NODE_ID )
12851313 } else {
12861314 // If we see: `struct Foo<T> where T: Copy { ... }`
1287- let ( fields, recovered) =
1288- self . parse_record_struct_body ( "struct" , generics. where_clause . has_where_token ) ?;
1315+ let ( fields, recovered) = self . parse_record_struct_body (
1316+ "struct" ,
1317+ generics. where_clause . has_where_token ,
1318+ Some ( start_span) ,
1319+ ) ?;
12891320 VariantData :: Struct ( fields, recovered)
12901321 }
12911322 // No `where` so: `struct Foo<T>;`
12921323 } else if self . eat ( & token:: Semi ) {
12931324 VariantData :: Unit ( DUMMY_NODE_ID )
12941325 // Record-style struct definition
12951326 } else if self . token == token:: OpenDelim ( token:: Brace ) {
1296- let ( fields, recovered) =
1297- self . parse_record_struct_body ( "struct" , generics. where_clause . has_where_token ) ?;
1327+ let ( fields, recovered) = self . parse_record_struct_body (
1328+ "struct" ,
1329+ generics. where_clause . has_where_token ,
1330+ Some ( start_span) ,
1331+ ) ?;
12981332 VariantData :: Struct ( fields, recovered)
12991333 // Tuple-style struct definition with optional where-clause.
13001334 } else if self . token == token:: OpenDelim ( token:: Paren ) {
@@ -1323,12 +1357,18 @@ impl<'a> Parser<'a> {
13231357
13241358 let vdata = if self . token . is_keyword ( kw:: Where ) {
13251359 generics. where_clause = self . parse_where_clause ( ) ?;
1326- let ( fields, recovered) =
1327- self . parse_record_struct_body ( "union" , generics. where_clause . has_where_token ) ?;
1360+ let ( fields, recovered) = self . parse_record_struct_body (
1361+ "union" ,
1362+ generics. where_clause . has_where_token ,
1363+ None ,
1364+ ) ?;
13281365 VariantData :: Struct ( fields, recovered)
13291366 } else if self . token == token:: OpenDelim ( token:: Brace ) {
1330- let ( fields, recovered) =
1331- self . parse_record_struct_body ( "union" , generics. where_clause . has_where_token ) ?;
1367+ let ( fields, recovered) = self . parse_record_struct_body (
1368+ "union" ,
1369+ generics. where_clause . has_where_token ,
1370+ None ,
1371+ ) ?;
13321372 VariantData :: Struct ( fields, recovered)
13331373 } else {
13341374 let token_str = super :: token_descr ( & self . token ) ;
@@ -1345,12 +1385,13 @@ impl<'a> Parser<'a> {
13451385 & mut self ,
13461386 adt_ty : & str ,
13471387 parsed_where : bool ,
1388+ start_span : Option < Span > ,
13481389 ) -> PResult < ' a , ( Vec < FieldDef > , /* recovered */ bool ) > {
13491390 let mut fields = Vec :: new ( ) ;
13501391 let mut recovered = false ;
13511392 if self . eat ( & token:: OpenDelim ( token:: Brace ) ) {
13521393 while self . token != token:: CloseDelim ( token:: Brace ) {
1353- let field = self . parse_field_def ( adt_ty) . map_err ( |e| {
1394+ let field = self . parse_field_def ( adt_ty, start_span ) . map_err ( |e| {
13541395 self . consume_block ( token:: Brace , ConsumeClosingDelim :: No ) ;
13551396 recovered = true ;
13561397 e
@@ -1413,12 +1454,15 @@ impl<'a> Parser<'a> {
14131454 }
14141455
14151456 /// Parses an element of a struct declaration.
1416- fn parse_field_def ( & mut self , adt_ty : & str ) -> PResult < ' a , FieldDef > {
1457+ fn parse_field_def ( & mut self , adt_ty : & str , start_span : Option < Span > ) -> PResult < ' a , FieldDef > {
14171458 let attrs = self . parse_outer_attributes ( ) ?;
14181459 self . collect_tokens_trailing_token ( attrs, ForceCollect :: No , |this, attrs| {
14191460 let lo = this. token . span ;
14201461 let vis = this. parse_visibility ( FollowedByType :: No ) ?;
1421- Ok ( ( this. parse_single_struct_field ( adt_ty, lo, vis, attrs) ?, TrailingToken :: None ) )
1462+ Ok ( (
1463+ this. parse_single_struct_field ( adt_ty, lo, vis, attrs, start_span) ?,
1464+ TrailingToken :: None ,
1465+ ) )
14221466 } )
14231467 }
14241468
@@ -1429,9 +1473,10 @@ impl<'a> Parser<'a> {
14291473 lo : Span ,
14301474 vis : Visibility ,
14311475 attrs : Vec < Attribute > ,
1476+ start_span : Option < Span > ,
14321477 ) -> PResult < ' a , FieldDef > {
14331478 let mut seen_comma: bool = false ;
1434- let a_var = self . parse_name_and_ty ( adt_ty, lo, vis, attrs) ?;
1479+ let a_var = self . parse_name_and_ty ( adt_ty, lo, vis, attrs, start_span ) ?;
14351480 if self . token == token:: Comma {
14361481 seen_comma = true ;
14371482 }
@@ -1555,9 +1600,32 @@ impl<'a> Parser<'a> {
15551600 lo : Span ,
15561601 vis : Visibility ,
15571602 attrs : Vec < Attribute > ,
1603+ start_span : Option < Span > ,
15581604 ) -> PResult < ' a , FieldDef > {
1605+ let prev_token_kind = self . prev_token . kind . clone ( ) ;
15591606 let name = self . parse_field_ident ( adt_ty, lo) ?;
1560- self . expect_field_ty_separator ( ) ?;
1607+ if let Err ( mut error) = self . expect_field_ty_separator ( ) {
1608+ if ( matches ! ( vis. kind, VisibilityKind :: Inherited )
1609+ && ( prev_token_kind == token:: Comma
1610+ || prev_token_kind == token:: OpenDelim ( token:: Brace ) ) )
1611+ || !matches ! ( vis. kind, VisibilityKind :: Inherited )
1612+ {
1613+ let snapshot = self . clone ( ) ;
1614+ if let Err ( err) = self . parse_ty ( ) {
1615+ if let Some ( span) = start_span {
1616+ error. span_suggestion_verbose (
1617+ span,
1618+ "consider using `enum` instead of `struct`" ,
1619+ "enum" . to_string ( ) ,
1620+ Applicability :: MaybeIncorrect ,
1621+ ) ;
1622+ }
1623+ err. cancel ( ) ;
1624+ * self = snapshot;
1625+ }
1626+ }
1627+ return Err ( error) ;
1628+ }
15611629 let ty = self . parse_ty ( ) ?;
15621630 if self . token . kind == token:: Colon && self . look_ahead ( 1 , |tok| tok. kind != token:: Colon ) {
15631631 self . struct_span_err ( self . token . span , "found single colon in a struct field type path" )
0 commit comments