@@ -12,7 +12,7 @@ use rustc_ast::ptr::P;
1212use  rustc_ast:: token; 
1313use  rustc_ast:: tokenstream:: TokenStream ; 
1414use  rustc_ast:: visit:: { self ,  AssocCtxt ,  Visitor } ; 
15- use  rustc_ast:: { AstLike ,  Block ,  Inline ,  ItemKind ,  Local ,   MacArgs ,  MacCall } ; 
15+ use  rustc_ast:: { AstLike ,  Block ,  Inline ,  ItemKind ,  MacArgs ,  MacCall } ; 
1616use  rustc_ast:: { MacCallStmt ,  MacStmtStyle ,  MetaItemKind ,  ModKind ,  NestedMetaItem } ; 
1717use  rustc_ast:: { NodeId ,  PatKind ,  Path ,  StmtKind ,  Unsafe } ; 
1818use  rustc_ast_pretty:: pprust; 
@@ -559,7 +559,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
559559        self . cx . force_mode  = orig_force_mode; 
560560
561561        // Finally incorporate all the expanded macros into the input AST fragment. 
562-         let  mut  placeholder_expander = PlaceholderExpander :: new ( self . cx ,   self . monotonic ) ; 
562+         let  mut  placeholder_expander = PlaceholderExpander :: default ( ) ; 
563563        while  let  Some ( expanded_fragments)  = expanded_fragments. pop ( )  { 
564564            for  ( expn_id,  expanded_fragment)  in  expanded_fragments. into_iter ( ) . rev ( )  { 
565565                placeholder_expander
@@ -1061,13 +1061,51 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
10611061        attr
10621062    } 
10631063
1064+     fn  take_stmt_bang ( 
1065+         & mut  self , 
1066+         stmt :  ast:: Stmt , 
1067+     )  -> Result < ( bool ,  MacCall ,  Vec < ast:: Attribute > ) ,  ast:: Stmt >  { 
1068+         match  stmt. kind  { 
1069+             StmtKind :: MacCall ( mac)  => { 
1070+                 let  MacCallStmt  {  mac,  style,  attrs,  .. }  = mac. into_inner ( ) ; 
1071+                 Ok ( ( style == MacStmtStyle :: Semicolon ,  mac,  attrs. into ( ) ) ) 
1072+             } 
1073+             StmtKind :: Item ( ref  item)  if  matches ! ( item. kind,  ItemKind :: MacCall ( ..) )  => { 
1074+                 match  stmt. kind  { 
1075+                     StmtKind :: Item ( item)  => match  item. into_inner ( )  { 
1076+                         ast:: Item  {  kind :  ItemKind :: MacCall ( mac) ,  attrs,  .. }  => { 
1077+                             Ok ( ( mac. args . need_semicolon ( ) ,  mac,  attrs) ) 
1078+                         } 
1079+                         _ => unreachable ! ( ) , 
1080+                     } , 
1081+                     _ => unreachable ! ( ) , 
1082+                 } 
1083+             } 
1084+             StmtKind :: Semi ( ref  expr)  if  matches ! ( expr. kind,  ast:: ExprKind :: MacCall ( ..) )  => { 
1085+                 match  stmt. kind  { 
1086+                     StmtKind :: Semi ( expr)  => match  expr. into_inner ( )  { 
1087+                         ast:: Expr  {  kind :  ast:: ExprKind :: MacCall ( mac) ,  attrs,  .. }  => { 
1088+                             Ok ( ( mac. args . need_semicolon ( ) ,  mac,  attrs. into ( ) ) ) 
1089+                         } 
1090+                         _ => unreachable ! ( ) , 
1091+                     } , 
1092+                     _ => unreachable ! ( ) , 
1093+                 } 
1094+             } 
1095+             StmtKind :: Local ( ..)  | StmtKind :: Empty  | StmtKind :: Item ( ..)  | StmtKind :: Semi ( ..)  => { 
1096+                 Err ( stmt) 
1097+             } 
1098+             StmtKind :: Expr ( ..)  => unreachable ! ( ) , 
1099+         } 
1100+     } 
1101+ 
10641102    fn  configure < T :  AstLike > ( & mut  self ,  node :  T )  -> Option < T >  { 
10651103        self . cfg . configure ( node) 
10661104    } 
10671105
10681106    // Detect use of feature-gated or invalid attributes on macro invocations 
10691107    // since they will not be detected after macro expansion. 
1070-     fn  check_attributes ( & mut   self ,  attrs :  & [ ast:: Attribute ] ,  call :  & MacCall )  { 
1108+     fn  check_attributes ( & self ,  attrs :  & [ ast:: Attribute ] ,  call :  & MacCall )  { 
10711109        let  features = self . cx . ecfg . features . unwrap ( ) ; 
10721110        let  mut  attrs = attrs. iter ( ) . peekable ( ) ; 
10731111        let  mut  span:  Option < Span >  = None ; 
@@ -1177,11 +1215,6 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
11771215        } ) ; 
11781216    } 
11791217
1180-     // This is needed in order to set `lint_node_id` for `let` statements 
1181-     fn  visit_local ( & mut  self ,  local :  & mut  P < Local > )  { 
1182-         assign_id ! ( self ,  & mut  local. id,  || noop_visit_local( local,  self ) ) ; 
1183-     } 
1184- 
11851218    fn  flat_map_arm ( & mut  self ,  arm :  ast:: Arm )  -> SmallVec < [ ast:: Arm ;  1 ] >  { 
11861219        let  mut  arm = configure ! ( self ,  arm) ; 
11871220
@@ -1299,31 +1332,39 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
12991332    fn  flat_map_stmt ( & mut  self ,  stmt :  ast:: Stmt )  -> SmallVec < [ ast:: Stmt ;  1 ] >  { 
13001333        let  mut  stmt = configure ! ( self ,  stmt) ; 
13011334
1302-         // we'll expand attributes on expressions separately 
1303-         if  !stmt. is_expr ( )  { 
1335+         // We pull macro invocations (both attributes and fn-like macro calls) out of their 
1336+         // `StmtKind`s and treat them as statement macro invocations, not as items or expressions. 
1337+         // FIXME: invocations in semicolon-less expressions positions are expanded as expressions, 
1338+         // changing that requires some compatibility measures. 
1339+         let  mut  stmt = if  !stmt. is_expr ( )  { 
13041340            if  let  Some ( attr)  = self . take_first_attr ( & mut  stmt)  { 
13051341                return  self 
13061342                    . collect_attr ( attr,  Annotatable :: Stmt ( P ( stmt) ) ,  AstFragmentKind :: Stmts ) 
13071343                    . make_stmts ( ) ; 
13081344            } 
1309-         } 
13101345
1311-         if  let  StmtKind :: MacCall ( mac)  = stmt. kind  { 
1312-             let  MacCallStmt  {  mac,  style,  attrs,  tokens :  _ }  = mac. into_inner ( ) ; 
1313-             self . check_attributes ( & attrs,  & mac) ; 
1314-             let  mut  placeholder =
1315-                 self . collect_bang ( mac,  stmt. span ,  AstFragmentKind :: Stmts ) . make_stmts ( ) ; 
1316- 
1317-             // If this is a macro invocation with a semicolon, then apply that 
1318-             // semicolon to the final statement produced by expansion. 
1319-             if  style == MacStmtStyle :: Semicolon  { 
1320-                 if  let  Some ( stmt)  = placeholder. pop ( )  { 
1321-                     placeholder. push ( stmt. add_trailing_semicolon ( ) ) ; 
1346+             let  span = stmt. span ; 
1347+             match  self . take_stmt_bang ( stmt)  { 
1348+                 Ok ( ( add_semicolon,  mac,  attrs) )  => { 
1349+                     self . check_attributes ( & attrs,  & mac) ; 
1350+                     let  mut  stmts =
1351+                         self . collect_bang ( mac,  span,  AstFragmentKind :: Stmts ) . make_stmts ( ) ; 
1352+ 
1353+                     // If this is a macro invocation with a semicolon, then apply that 
1354+                     // semicolon to the final statement produced by expansion. 
1355+                     if  add_semicolon { 
1356+                         if  let  Some ( stmt)  = stmts. pop ( )  { 
1357+                             stmts. push ( stmt. add_trailing_semicolon ( ) ) ; 
1358+                         } 
1359+                     } 
1360+ 
1361+                     return  stmts; 
13221362                } 
1363+                 Err ( stmt)  => stmt, 
13231364            } 
1324- 
1325-             return  placeholder ; 
1326-         } 
1365+          }   else   { 
1366+             stmt 
1367+         } ; 
13271368
13281369        // The only way that we can end up with a `MacCall` expression statement, 
13291370        // (as opposed to a `StmtKind::MacCall`) is if we have a macro as the 
@@ -1338,14 +1379,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
13381379            } 
13391380        } 
13401381
1341-         // The placeholder expander gives ids to statements, so we avoid folding the id here. 
1342-         // We don't use `assign_id!` - it will be called when we visit statement's contents 
1343-         // (e.g. an expression, item, or local) 
1344-         let  ast:: Stmt  {  id,  kind,  span }  = stmt; 
1345-         let  res = noop_flat_map_stmt_kind ( kind,  self ) 
1346-             . into_iter ( ) 
1347-             . map ( |kind| ast:: Stmt  {  id,  kind,  span } ) 
1348-             . collect ( ) ; 
1382+         let  res = assign_id ! ( self ,  & mut  stmt. id,  || noop_flat_map_stmt( stmt,  self ) ) ; 
13491383
13501384        self . cx . current_expansion . is_trailing_mac  = false ; 
13511385        res
0 commit comments