@@ -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
@@ -1341,6 +1342,10 @@ impl<'a> Parser<'a> {
1341
1342
let vlo = self . token . span ;
1342
1343
1343
1344
let vis = self . parse_visibility ( FollowedByType :: No ) ?;
1345
+ if !self . recover_nested_adt_item ( kw:: Enum ) ? {
1346
+ // Item already parsed, we need to skip this variant.
1347
+ continue
1348
+ }
1344
1349
let ident = self . parse_ident ( ) ?;
1345
1350
1346
1351
let struct_def = if self . check ( & token:: OpenDelim ( token:: Brace ) ) {
@@ -1742,6 +1747,36 @@ impl<'a> Parser<'a> {
1742
1747
) . emit ( ) ;
1743
1748
}
1744
1749
1750
+ /// Checks if current token is one of tokens which cannot be nested like `kw::Enum`. In case
1751
+ /// it is, we try to parse the item and report error about nested types.
1752
+ fn recover_nested_adt_item ( & mut self , keyword : Symbol ) -> PResult < ' a , bool > {
1753
+ if self . token . is_keyword ( kw:: Enum ) ||
1754
+ self . token . is_keyword ( kw:: Struct ) ||
1755
+ self . token . is_keyword ( kw:: Union ) {
1756
+
1757
+ let prev_token = self . token . clone ( ) ;
1758
+ let item = self . parse_item ( ) ?;
1759
+ if self . token == token:: Comma {
1760
+ self . bump ( ) ;
1761
+ }
1762
+
1763
+ let mut err = self . struct_span_err (
1764
+ prev_token. span ,
1765
+ & format ! ( "`{}` definition cannot be nested inside `{}`" , pprust:: token_to_string( & prev_token) , keyword) ,
1766
+ ) ;
1767
+ err. span_suggestion (
1768
+ item. unwrap ( ) . span ,
1769
+ & format ! ( "consider creating a new `{}` definition instead of nesting" , pprust:: token_to_string( & prev_token) ) ,
1770
+ String :: new ( ) ,
1771
+ Applicability :: MaybeIncorrect ,
1772
+ ) ;
1773
+ err. emit ( ) ;
1774
+ // We successfully parsed the item but we must inform the caller about nested problem.
1775
+ return Ok ( false )
1776
+ }
1777
+ Ok ( true )
1778
+ }
1779
+
1745
1780
fn mk_item ( & self , span : Span , ident : Ident , kind : ItemKind , vis : Visibility ,
1746
1781
attrs : Vec < Attribute > ) -> P < Item > {
1747
1782
P ( Item {
0 commit comments