@@ -30,7 +30,7 @@ impl<'a> Parser<'a> {
30
30
31
31
fn parse_item_ ( & mut self , req_name : ReqName ) -> PResult < ' a , Option < Item > > {
32
32
let attrs = self . parse_outer_attributes ( ) ?;
33
- self . parse_item_common ( attrs, true , false , req_name)
33
+ self . parse_item_common ( attrs, true , false , req_name, true )
34
34
}
35
35
36
36
pub ( super ) fn parse_item_common (
@@ -39,6 +39,7 @@ impl<'a> Parser<'a> {
39
39
mac_allowed : bool ,
40
40
attrs_allowed : bool ,
41
41
req_name : ReqName ,
42
+ mod_stmt : bool ,
42
43
) -> PResult < ' a , Option < Item > > {
43
44
maybe_whole ! ( self , NtItem , |item| {
44
45
let mut item = item;
@@ -49,9 +50,9 @@ impl<'a> Parser<'a> {
49
50
50
51
let mut unclosed_delims = vec ! [ ] ;
51
52
let ( mut item, tokens) = self . collect_tokens ( |this| {
52
- let item = this. parse_item_common_ ( attrs, mac_allowed, attrs_allowed, req_name) ;
53
+ let i = this. parse_item_common_ ( attrs, mac_allowed, attrs_allowed, req_name, mod_stmt ) ;
53
54
unclosed_delims. append ( & mut this. unclosed_delims ) ;
54
- item
55
+ i
55
56
} ) ?;
56
57
self . unclosed_delims . append ( & mut unclosed_delims) ;
57
58
@@ -83,11 +84,13 @@ impl<'a> Parser<'a> {
83
84
mac_allowed : bool ,
84
85
attrs_allowed : bool ,
85
86
req_name : ReqName ,
87
+ mod_stmt : bool ,
86
88
) -> PResult < ' a , Option < Item > > {
87
89
let lo = self . token . span ;
88
90
let vis = self . parse_visibility ( FollowedByType :: No ) ?;
89
91
let mut def = self . parse_defaultness ( ) ;
90
- let kind = self . parse_item_kind ( & mut attrs, mac_allowed, lo, & vis, & mut def, req_name) ?;
92
+ let kind =
93
+ self . parse_item_kind ( & mut attrs, mac_allowed, lo, & vis, & mut def, req_name, mod_stmt) ?;
91
94
if let Some ( ( ident, kind) ) = kind {
92
95
self . error_on_unconsumed_default ( def, & kind) ;
93
96
let span = lo. to ( self . prev_span ) ;
@@ -148,6 +151,7 @@ impl<'a> Parser<'a> {
148
151
vis : & Visibility ,
149
152
def : & mut Defaultness ,
150
153
req_name : ReqName ,
154
+ mod_stmt : bool ,
151
155
) -> PResult < ' a , Option < ItemInfo > > {
152
156
let mut def = || mem:: replace ( def, Defaultness :: Final ) ;
153
157
@@ -212,9 +216,13 @@ impl<'a> Parser<'a> {
212
216
} else if vis. node . is_pub ( ) && self . isnt_macro_invocation ( ) {
213
217
self . recover_missing_kw_before_item ( ) ?;
214
218
return Ok ( None ) ;
215
- } else if macros_allowed && self . token . is_path_start ( ) {
219
+ } else if let Some ( kind) = if macros_allowed && self . token . is_path_start ( ) {
220
+ self . parse_item_macro ( vis, mod_stmt) ?
221
+ } else {
222
+ None
223
+ } {
216
224
// MACRO INVOCATION ITEM
217
- ( Ident :: invalid ( ) , ItemKind :: Mac ( self . parse_item_macro ( vis ) ? ) )
225
+ ( Ident :: invalid ( ) , ItemKind :: Mac ( kind ) )
218
226
} else {
219
227
return Ok ( None ) ;
220
228
} ;
@@ -333,13 +341,36 @@ impl<'a> Parser<'a> {
333
341
}
334
342
335
343
/// Parses an item macro, e.g., `item!();`.
336
- fn parse_item_macro ( & mut self , vis : & Visibility ) -> PResult < ' a , Mac > {
337
- let path = self . parse_path ( PathStyle :: Mod ) ?; // `foo::bar`
338
- self . expect ( & token:: Not ) ?; // `!`
344
+ fn parse_item_macro ( & mut self , vis : & Visibility , mod_stmt : bool ) -> PResult < ' a , Option < Mac > > {
345
+ let parse_prefix = |p : & mut Self | -> PResult < ' a , ast:: Path > {
346
+ let path = p. parse_path ( PathStyle :: Mod ) ?; // `foo::bar`
347
+ p. expect ( & token:: Not ) ?; // `!`
348
+ Ok ( path)
349
+ } ;
350
+ let path = if mod_stmt {
351
+ // We're in statement-as-module-item recovery mode.
352
+ // To avoid "stealing" syntax from e.g. `x.f()` as a module-level statement,
353
+ // we backtrack if we failed to parse `$path!`; after we have, we commit firmly.
354
+ // This is only done when `mod_stmt` holds to avoid backtracking inside functions.
355
+ let snapshot = self . clone ( ) ;
356
+ match parse_prefix ( self ) {
357
+ Ok ( path) => path,
358
+ Err ( mut err) => {
359
+ // Assert that this is only for diagnostics!
360
+ // This is a safeguard against breaking LL(k) accidentally in the spec,
361
+ // assuming no one has gated the syntax with something like `#[cfg(FALSE)]`.
362
+ err. delay_as_bug ( ) ;
363
+ * self = snapshot;
364
+ return Ok ( None ) ;
365
+ }
366
+ }
367
+ } else {
368
+ parse_prefix ( self ) ?
369
+ } ;
339
370
let args = self . parse_mac_args ( ) ?; // `( .. )` or `[ .. ]` (followed by `;`), or `{ .. }`.
340
371
self . eat_semi_for_macro_if_needed ( & args) ;
341
372
self . complain_if_pub_macro ( vis, false ) ;
342
- Ok ( Mac { path, args, prior_type_ascription : self . last_type_ascription } )
373
+ Ok ( Some ( Mac { path, args, prior_type_ascription : self . last_type_ascription } ) )
343
374
}
344
375
345
376
/// Recover if we parsed attributes and expected an item but there was none.
0 commit comments