@@ -9,14 +9,15 @@ use syntax::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness
9
9
use syntax:: ast:: { Visibility , VisibilityKind , Mutability , FnHeader , ForeignItem , ForeignItemKind } ;
10
10
use syntax:: ast:: { Ty , TyKind , Generics , TraitRef , EnumDef , VariantData , StructField } ;
11
11
use syntax:: ast:: { Mac , MacDelimiter , Block , BindingMode , FnDecl , FnSig , SelfKind , Param } ;
12
+ use syntax:: print:: pprust;
12
13
use syntax:: ptr:: P ;
13
14
use syntax:: ThinVec ;
14
15
use syntax:: token;
15
16
use syntax:: tokenstream:: { TokenTree , TokenStream } ;
16
17
use syntax:: source_map:: { self , respan, Span } ;
17
18
use syntax:: struct_span_err;
18
19
use syntax_pos:: BytePos ;
19
- use syntax_pos:: symbol:: { kw, sym} ;
20
+ use syntax_pos:: symbol:: { kw, sym, Symbol } ;
20
21
21
22
use rustc_error_codes:: * ;
22
23
@@ -1336,11 +1337,17 @@ impl<'a> Parser<'a> {
1336
1337
/// Parses the part of an enum declaration following the `{`.
1337
1338
fn parse_enum_def ( & mut self , _generics : & Generics ) -> PResult < ' a , EnumDef > {
1338
1339
let mut variants = Vec :: new ( ) ;
1340
+ // FIXME: Consider using `parse_delim_comma_seq`.
1341
+ // We could then remove eating comma in `recover_nested_adt_item`.
1339
1342
while self . token != token:: CloseDelim ( token:: Brace ) {
1340
1343
let variant_attrs = self . parse_outer_attributes ( ) ?;
1341
1344
let vlo = self . token . span ;
1342
1345
1343
1346
let vis = self . parse_visibility ( FollowedByType :: No ) ?;
1347
+ if !self . recover_nested_adt_item ( kw:: Enum ) ? {
1348
+ // Item already parsed, we need to skip this variant.
1349
+ continue
1350
+ }
1344
1351
let ident = self . parse_ident ( ) ?;
1345
1352
1346
1353
let struct_def = if self . check ( & token:: OpenDelim ( token:: Brace ) ) {
@@ -1742,6 +1749,33 @@ impl<'a> Parser<'a> {
1742
1749
) . emit ( ) ;
1743
1750
}
1744
1751
1752
+ /// Checks if current token is one of tokens which cannot be nested like `kw::Enum`. In case
1753
+ /// it is, we try to parse the item and report error about nested types.
1754
+ fn recover_nested_adt_item ( & mut self , keyword : Symbol ) -> PResult < ' a , bool > {
1755
+ if self . token . is_keyword ( kw:: Enum ) ||
1756
+ self . token . is_keyword ( kw:: Struct ) ||
1757
+ self . token . is_keyword ( kw:: Union )
1758
+ {
1759
+ let kw_token = self . token . clone ( ) ;
1760
+ let kw_str = pprust:: token_to_string ( & kw_token) ;
1761
+ let item = self . parse_item ( ) ?;
1762
+ self . eat ( & token:: Comma ) ;
1763
+
1764
+ self . struct_span_err (
1765
+ kw_token. span ,
1766
+ & format ! ( "`{}` definition cannot be nested inside `{}`" , kw_str, keyword) ,
1767
+ ) . span_suggestion (
1768
+ item. unwrap ( ) . span ,
1769
+ & format ! ( "consider creating a new `{}` definition instead of nesting" , kw_str) ,
1770
+ String :: new ( ) ,
1771
+ Applicability :: MaybeIncorrect ,
1772
+ ) . emit ( ) ;
1773
+ // We successfully parsed the item but we must inform the caller about nested problem.
1774
+ return Ok ( false )
1775
+ }
1776
+ Ok ( true )
1777
+ }
1778
+
1745
1779
fn mk_item ( & self , span : Span , ident : Ident , kind : ItemKind , vis : Visibility ,
1746
1780
attrs : Vec < Attribute > ) -> P < Item > {
1747
1781
P ( Item {
0 commit comments