@@ -85,12 +85,18 @@ pub enum PathStyle {
85
85
Expr ,
86
86
}
87
87
88
- #[ derive( Clone , Copy , PartialEq ) ]
88
+ #[ derive( Clone , Copy , Debug , PartialEq ) ]
89
89
pub enum SemiColonMode {
90
90
Break ,
91
91
Ignore ,
92
92
}
93
93
94
+ #[ derive( Clone , Copy , Debug , PartialEq ) ]
95
+ pub enum BlockMode {
96
+ Break ,
97
+ Ignore ,
98
+ }
99
+
94
100
/// Possibly accept an `token::Interpolated` expression (a pre-parsed expression
95
101
/// dropped into the token stream, which happens while parsing the result of
96
102
/// macro expansion). Placement of these is not as complex as I feared it would
@@ -1204,7 +1210,7 @@ impl<'a> Parser<'a> {
1204
1210
}
1205
1211
1206
1212
/// Parse the items in a trait declaration
1207
- pub fn parse_trait_item ( & mut self ) -> PResult < ' a , TraitItem > {
1213
+ pub fn parse_trait_item ( & mut self , at_end : & mut bool ) -> PResult < ' a , TraitItem > {
1208
1214
maybe_whole ! ( self , NtTraitItem , |x| x) ;
1209
1215
let mut attrs = self . parse_outer_attributes ( ) ?;
1210
1216
let lo = self . span ;
@@ -1214,7 +1220,7 @@ impl<'a> Parser<'a> {
1214
1220
self . expect ( & token:: Semi ) ?;
1215
1221
( ident, TraitItemKind :: Type ( bounds, default) )
1216
1222
} else if self . is_const_item ( ) {
1217
- self . expect_keyword ( keywords:: Const ) ?;
1223
+ self . expect_keyword ( keywords:: Const ) ?;
1218
1224
let ident = self . parse_ident ( ) ?;
1219
1225
self . expect ( & token:: Colon ) ?;
1220
1226
let ty = self . parse_ty ( ) ?;
@@ -1231,9 +1237,17 @@ impl<'a> Parser<'a> {
1231
1237
} else if self . token . is_path_start ( ) {
1232
1238
// trait item macro.
1233
1239
// code copied from parse_macro_use_or_failure... abstraction!
1240
+ let prev_span = self . prev_span ;
1234
1241
let lo = self . span ;
1235
1242
let pth = self . parse_path ( PathStyle :: Mod ) ?;
1236
- self . expect ( & token:: Not ) ?;
1243
+
1244
+ if pth. segments . len ( ) == 1 {
1245
+ if !self . eat ( & token:: Not ) {
1246
+ return Err ( self . missing_assoc_item_kind_err ( "trait" , prev_span) ) ;
1247
+ }
1248
+ } else {
1249
+ self . expect ( & token:: Not ) ?;
1250
+ }
1237
1251
1238
1252
// eat a matched-delimiter token tree:
1239
1253
let ( delim, tts) = self . expect_delimited_token_tree ( ) ?;
@@ -1246,25 +1260,7 @@ impl<'a> Parser<'a> {
1246
1260
} else {
1247
1261
let ( constness, unsafety, abi) = match self . parse_fn_front_matter ( ) {
1248
1262
Ok ( cua) => cua,
1249
- Err ( e) => {
1250
- loop {
1251
- match self . token {
1252
- token:: Eof => break ,
1253
- token:: CloseDelim ( token:: Brace ) |
1254
- token:: Semi => {
1255
- self . bump ( ) ;
1256
- break ;
1257
- }
1258
- token:: OpenDelim ( token:: Brace ) => {
1259
- self . parse_token_tree ( ) ;
1260
- break ;
1261
- }
1262
- _ => self . bump ( ) ,
1263
- }
1264
- }
1265
-
1266
- return Err ( e) ;
1267
- }
1263
+ Err ( e) => return Err ( e) ,
1268
1264
} ;
1269
1265
1270
1266
let ident = self . parse_ident ( ) ?;
@@ -1289,11 +1285,13 @@ impl<'a> Parser<'a> {
1289
1285
let body = match self . token {
1290
1286
token:: Semi => {
1291
1287
self . bump ( ) ;
1288
+ * at_end = true ;
1292
1289
debug ! ( "parse_trait_methods(): parsing required method" ) ;
1293
1290
None
1294
1291
}
1295
1292
token:: OpenDelim ( token:: Brace ) => {
1296
1293
debug ! ( "parse_trait_methods(): parsing provided method" ) ;
1294
+ * at_end = true ;
1297
1295
let ( inner_attrs, body) = self . parse_inner_attrs_and_block ( ) ?;
1298
1296
attrs. extend ( inner_attrs. iter ( ) . cloned ( ) ) ;
1299
1297
Some ( body)
@@ -1315,18 +1313,6 @@ impl<'a> Parser<'a> {
1315
1313
} )
1316
1314
}
1317
1315
1318
-
1319
- /// Parse the items in a trait declaration
1320
- pub fn parse_trait_items ( & mut self ) -> PResult < ' a , Vec < TraitItem > > {
1321
- self . parse_unspanned_seq (
1322
- & token:: OpenDelim ( token:: Brace ) ,
1323
- & token:: CloseDelim ( token:: Brace ) ,
1324
- SeqSep :: none ( ) ,
1325
- |p| -> PResult < ' a , TraitItem > {
1326
- p. parse_trait_item ( )
1327
- } )
1328
- }
1329
-
1330
1316
/// Parse optional return type [ -> TY ] in function decl
1331
1317
pub fn parse_ret_ty ( & mut self ) -> PResult < ' a , FunctionRetTy > {
1332
1318
if self . eat ( & token:: RArrow ) {
@@ -3641,22 +3627,33 @@ impl<'a> Parser<'a> {
3641
3627
//
3642
3628
// We terminate when we find an unmatched `}` (without consuming it).
3643
3629
fn recover_stmt ( & mut self ) {
3644
- self . recover_stmt_ ( SemiColonMode :: Ignore )
3630
+ self . recover_stmt_ ( SemiColonMode :: Ignore , BlockMode :: Ignore )
3645
3631
}
3632
+
3646
3633
// If `break_on_semi` is `Break`, then we will stop consuming tokens after
3647
3634
// finding (and consuming) a `;` outside of `{}` or `[]` (note that this is
3648
3635
// approximate - it can mean we break too early due to macros, but that
3649
3636
// shoud only lead to sub-optimal recovery, not inaccurate parsing).
3650
- fn recover_stmt_ ( & mut self , break_on_semi : SemiColonMode ) {
3637
+ //
3638
+ // If `break_on_block` is `Break`, then we will stop consuming tokens
3639
+ // after finding (and consuming) a brace-delimited block.
3640
+ fn recover_stmt_ ( & mut self , break_on_semi : SemiColonMode , break_on_block : BlockMode ) {
3651
3641
let mut brace_depth = 0 ;
3652
3642
let mut bracket_depth = 0 ;
3653
- debug ! ( "recover_stmt_ enter loop" ) ;
3643
+ let mut in_block = false ;
3644
+ debug ! ( "recover_stmt_ enter loop (semi={:?}, block={:?})" ,
3645
+ break_on_semi, break_on_block) ;
3654
3646
loop {
3655
3647
debug ! ( "recover_stmt_ loop {:?}" , self . token) ;
3656
3648
match self . token {
3657
3649
token:: OpenDelim ( token:: DelimToken :: Brace ) => {
3658
3650
brace_depth += 1 ;
3659
3651
self . bump ( ) ;
3652
+ if break_on_block == BlockMode :: Break &&
3653
+ brace_depth == 1 &&
3654
+ bracket_depth == 0 {
3655
+ in_block = true ;
3656
+ }
3660
3657
}
3661
3658
token:: OpenDelim ( token:: DelimToken :: Bracket ) => {
3662
3659
bracket_depth += 1 ;
@@ -3669,6 +3666,10 @@ impl<'a> Parser<'a> {
3669
3666
}
3670
3667
brace_depth -= 1 ;
3671
3668
self . bump ( ) ;
3669
+ if in_block && bracket_depth == 0 && brace_depth == 0 {
3670
+ debug ! ( "recover_stmt_ return - block end {:?}" , self . token) ;
3671
+ return ;
3672
+ }
3672
3673
}
3673
3674
token:: CloseDelim ( token:: DelimToken :: Bracket ) => {
3674
3675
bracket_depth -= 1 ;
@@ -3700,7 +3701,7 @@ impl<'a> Parser<'a> {
3700
3701
fn parse_stmt_ ( & mut self , macro_legacy_warnings : bool ) -> Option < Stmt > {
3701
3702
self . parse_stmt_without_recovery ( macro_legacy_warnings) . unwrap_or_else ( |mut e| {
3702
3703
e. emit ( ) ;
3703
- self . recover_stmt_ ( SemiColonMode :: Break ) ;
3704
+ self . recover_stmt_ ( SemiColonMode :: Break , BlockMode :: Ignore ) ;
3704
3705
None
3705
3706
} )
3706
3707
}
@@ -3974,7 +3975,7 @@ impl<'a> Parser<'a> {
3974
3975
e. span_suggestion ( stmt_span, "try placing this code inside a block" , sugg) ;
3975
3976
}
3976
3977
Err ( mut e) => {
3977
- self . recover_stmt_ ( SemiColonMode :: Break ) ;
3978
+ self . recover_stmt_ ( SemiColonMode :: Break , BlockMode :: Ignore ) ;
3978
3979
self . cancel ( & mut e) ;
3979
3980
}
3980
3981
_ => ( )
@@ -4663,7 +4664,7 @@ impl<'a> Parser<'a> {
4663
4664
}
4664
4665
4665
4666
/// Parse an impl item.
4666
- pub fn parse_impl_item ( & mut self ) -> PResult < ' a , ImplItem > {
4667
+ pub fn parse_impl_item ( & mut self , at_end : & mut bool ) -> PResult < ' a , ImplItem > {
4667
4668
maybe_whole ! ( self , NtImplItem , |x| x) ;
4668
4669
4669
4670
let mut attrs = self . parse_outer_attributes ( ) ?;
@@ -4686,7 +4687,7 @@ impl<'a> Parser<'a> {
4686
4687
self . expect ( & token:: Semi ) ?;
4687
4688
( name, ast:: ImplItemKind :: Const ( typ, expr) )
4688
4689
} else {
4689
- let ( name, inner_attrs, node) = self . parse_impl_method ( & vis) ?;
4690
+ let ( name, inner_attrs, node) = self . parse_impl_method ( & vis, at_end ) ?;
4690
4691
attrs. extend ( inner_attrs) ;
4691
4692
( name, node)
4692
4693
} ;
@@ -4731,43 +4732,50 @@ impl<'a> Parser<'a> {
4731
4732
}
4732
4733
}
4733
4734
4735
+ fn missing_assoc_item_kind_err ( & mut self , item_type : & str , prev_span : Span )
4736
+ -> DiagnosticBuilder < ' a >
4737
+ {
4738
+ // Given this code `path(`, it seems like this is not
4739
+ // setting the visibility of a macro invocation, but rather
4740
+ // a mistyped method declaration.
4741
+ // Create a diagnostic pointing out that `fn` is missing.
4742
+ //
4743
+ // x | pub path(&self) {
4744
+ // | ^ missing `fn`, `type`, or `const`
4745
+ // pub path(
4746
+ // ^^ `sp` below will point to this
4747
+ let sp = prev_span. between ( self . prev_span ) ;
4748
+ let mut err = self . diagnostic ( ) . struct_span_err (
4749
+ sp,
4750
+ & format ! ( "missing `fn`, `type`, or `const` for {}-item declaration" ,
4751
+ item_type) ) ;
4752
+ err. span_label ( sp, & "missing `fn`, `type`, or `const`" ) ;
4753
+ err
4754
+ }
4755
+
4734
4756
/// Parse a method or a macro invocation in a trait impl.
4735
- fn parse_impl_method ( & mut self , vis : & Visibility )
4757
+ fn parse_impl_method ( & mut self , vis : & Visibility , at_end : & mut bool )
4736
4758
-> PResult < ' a , ( Ident , Vec < ast:: Attribute > , ast:: ImplItemKind ) > {
4737
4759
// code copied from parse_macro_use_or_failure... abstraction!
4738
4760
if self . token . is_path_start ( ) {
4739
4761
// Method macro.
4740
4762
4741
4763
let prev_span = self . prev_span ;
4742
- // Before complaining about trying to set a macro as `pub`,
4743
- // check if `!` comes after the path.
4744
- let err = self . complain_if_pub_macro_diag ( & vis, prev_span) ;
4745
4764
4746
4765
let lo = self . span ;
4747
4766
let pth = self . parse_path ( PathStyle :: Mod ) ?;
4748
- let bang_err = self . expect ( & token:: Not ) ;
4749
- if let Err ( mut err) = err {
4750
- if let Err ( mut bang_err) = bang_err {
4751
- // Given this code `pub path(`, it seems like this is not setting the
4752
- // visibility of a macro invocation, but rather a mistyped method declaration.
4753
- // Create a diagnostic pointing out that `fn` is missing.
4754
- //
4755
- // x | pub path(&self) {
4756
- // | ^ missing `fn` for method declaration
4757
-
4758
- err. cancel ( ) ;
4759
- bang_err. cancel ( ) ;
4760
- // pub path(
4761
- // ^^ `sp` below will point to this
4762
- let sp = prev_span. between ( self . prev_span ) ;
4763
- err = self . diagnostic ( )
4764
- . struct_span_err ( sp, "missing `fn` for method declaration" ) ;
4765
- err. span_label ( sp, & "missing `fn`" ) ;
4767
+ if pth. segments . len ( ) == 1 {
4768
+ if !self . eat ( & token:: Not ) {
4769
+ return Err ( self . missing_assoc_item_kind_err ( "impl" , prev_span) ) ;
4766
4770
}
4767
- return Err ( err) ;
4771
+ } else {
4772
+ self . expect ( & token:: Not ) ?;
4768
4773
}
4769
4774
4775
+ self . complain_if_pub_macro ( & vis, prev_span) ;
4776
+
4770
4777
// eat a matched-delimiter token tree:
4778
+ * at_end = true ;
4771
4779
let ( delim, tts) = self . expect_delimited_token_tree ( ) ?;
4772
4780
if delim != token:: Brace {
4773
4781
self . expect ( & token:: Semi ) ?
@@ -4781,6 +4789,7 @@ impl<'a> Parser<'a> {
4781
4789
let mut generics = self . parse_generics ( ) ?;
4782
4790
let decl = self . parse_fn_decl_with_self ( |p| p. parse_arg ( ) ) ?;
4783
4791
generics. where_clause = self . parse_where_clause ( ) ?;
4792
+ * at_end = true ;
4784
4793
let ( inner_attrs, body) = self . parse_inner_attrs_and_block ( ) ?;
4785
4794
Ok ( ( ident, inner_attrs, ast:: ImplItemKind :: Method ( ast:: MethodSig {
4786
4795
generics : generics,
@@ -4806,8 +4815,21 @@ impl<'a> Parser<'a> {
4806
4815
4807
4816
tps. where_clause = self . parse_where_clause ( ) ?;
4808
4817
4809
- let meths = self . parse_trait_items ( ) ?;
4810
- Ok ( ( ident, ItemKind :: Trait ( unsafety, tps, bounds, meths) , None ) )
4818
+ self . expect ( & token:: OpenDelim ( token:: Brace ) ) ?;
4819
+ let mut trait_items = vec ! [ ] ;
4820
+ while !self . eat ( & token:: CloseDelim ( token:: Brace ) ) {
4821
+ let mut at_end = false ;
4822
+ match self . parse_trait_item ( & mut at_end) {
4823
+ Ok ( item) => trait_items. push ( item) ,
4824
+ Err ( mut e) => {
4825
+ e. emit ( ) ;
4826
+ if !at_end {
4827
+ self . recover_stmt_ ( SemiColonMode :: Break , BlockMode :: Break ) ;
4828
+ }
4829
+ }
4830
+ }
4831
+ }
4832
+ Ok ( ( ident, ItemKind :: Trait ( unsafety, tps, bounds, trait_items) , None ) )
4811
4833
}
4812
4834
4813
4835
/// Parses items implementations variants
@@ -4882,7 +4904,16 @@ impl<'a> Parser<'a> {
4882
4904
4883
4905
let mut impl_items = vec ! [ ] ;
4884
4906
while !self . eat ( & token:: CloseDelim ( token:: Brace ) ) {
4885
- impl_items. push ( self . parse_impl_item ( ) ?) ;
4907
+ let mut at_end = false ;
4908
+ match self . parse_impl_item ( & mut at_end) {
4909
+ Ok ( item) => impl_items. push ( item) ,
4910
+ Err ( mut e) => {
4911
+ e. emit ( ) ;
4912
+ if !at_end {
4913
+ self . recover_stmt_ ( SemiColonMode :: Break , BlockMode :: Break ) ;
4914
+ }
4915
+ }
4916
+ }
4886
4917
}
4887
4918
4888
4919
Ok ( ( keywords:: Invalid . ident ( ) ,
0 commit comments