@@ -30,7 +30,7 @@ impl<'a> Parser<'a> {
3030
3131 fn parse_item_ ( & mut self , req_name : ReqName ) -> PResult < ' a , Option < Item > > {
3232 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 )
3434 }
3535
3636 pub ( super ) fn parse_item_common (
@@ -39,6 +39,7 @@ impl<'a> Parser<'a> {
3939 mac_allowed : bool ,
4040 attrs_allowed : bool ,
4141 req_name : ReqName ,
42+ mod_stmt : bool ,
4243 ) -> PResult < ' a , Option < Item > > {
4344 maybe_whole ! ( self , NtItem , |item| {
4445 let mut item = item;
@@ -49,9 +50,9 @@ impl<'a> Parser<'a> {
4950
5051 let mut unclosed_delims = vec ! [ ] ;
5152 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 ) ;
5354 unclosed_delims. append ( & mut this. unclosed_delims ) ;
54- item
55+ i
5556 } ) ?;
5657 self . unclosed_delims . append ( & mut unclosed_delims) ;
5758
@@ -83,11 +84,13 @@ impl<'a> Parser<'a> {
8384 mac_allowed : bool ,
8485 attrs_allowed : bool ,
8586 req_name : ReqName ,
87+ mod_stmt : bool ,
8688 ) -> PResult < ' a , Option < Item > > {
8789 let lo = self . token . span ;
8890 let vis = self . parse_visibility ( FollowedByType :: No ) ?;
8991 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) ?;
9194 if let Some ( ( ident, kind) ) = kind {
9295 self . error_on_unconsumed_default ( def, & kind) ;
9396 let span = lo. to ( self . prev_span ) ;
@@ -148,6 +151,7 @@ impl<'a> Parser<'a> {
148151 vis : & Visibility ,
149152 def : & mut Defaultness ,
150153 req_name : ReqName ,
154+ mod_stmt : bool ,
151155 ) -> PResult < ' a , Option < ItemInfo > > {
152156 let mut def = || mem:: replace ( def, Defaultness :: Final ) ;
153157
@@ -212,9 +216,13 @@ impl<'a> Parser<'a> {
212216 } else if vis. node . is_pub ( ) && self . isnt_macro_invocation ( ) {
213217 self . recover_missing_kw_before_item ( ) ?;
214218 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+ } {
216224 // MACRO INVOCATION ITEM
217- ( Ident :: invalid ( ) , ItemKind :: Mac ( self . parse_item_macro ( vis ) ? ) )
225+ ( Ident :: invalid ( ) , ItemKind :: Mac ( kind ) )
218226 } else {
219227 return Ok ( None ) ;
220228 } ;
@@ -333,13 +341,36 @@ impl<'a> Parser<'a> {
333341 }
334342
335343 /// 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+ } ;
339370 let args = self . parse_mac_args ( ) ?; // `( .. )` or `[ .. ]` (followed by `;`), or `{ .. }`.
340371 self . eat_semi_for_macro_if_needed ( & args) ;
341372 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 } ) )
343374 }
344375
345376 /// Recover if we parsed attributes and expected an item but there was none.
0 commit comments