@@ -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