@@ -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 , MacArgs } ;
15+ use rustc_ast:: { AstLike , Block , Inline , ItemKind , Local , MacArgs } ;
1616use rustc_ast:: { MacCallStmt , MacStmtStyle , MetaItemKind , ModKind , NestedMetaItem } ;
1717use rustc_ast:: { NodeId , PatKind , Path , StmtKind , Unsafe } ;
1818use rustc_ast_pretty:: pprust;
@@ -1098,6 +1098,43 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
10981098 }
10991099}
11001100
1101+ /// Wraps a call to `noop_visit_*` / `noop_flat_map_*`
1102+ /// for an AST node that supports attributes
1103+ /// (see the `Annotatable` enum)
1104+ /// This method assigns a `NodeId`, and sets that `NodeId`
1105+ /// as our current 'lint node id'. If a macro call is found
1106+ /// inside this AST node, we will use this AST node's `NodeId`
1107+ /// to emit lints associated with that macro (allowing
1108+ /// `#[allow]` / `#[deny]` to be applied close to
1109+ /// the macro invocation).
1110+ ///
1111+ /// Do *not* call this for a macro AST node
1112+ /// (e.g. `ExprKind::MacCall`) - we cannot emit lints
1113+ /// at these AST nodes, since they are removed and
1114+ /// replaced with the result of macro expansion.
1115+ ///
1116+ /// All other `NodeId`s are assigned by `visit_id`.
1117+ /// * `self` is the 'self' parameter for the current method,
1118+ /// * `id` is a mutable reference to the `NodeId` field
1119+ /// of the current AST node.
1120+ /// * `closure` is a closure that executes the
1121+ /// `noop_visit_*` / `noop_flat_map_*` method
1122+ /// for the current AST node.
1123+ macro_rules! assign_id {
1124+ ( $self: ident, $id: expr, $closure: expr) => { {
1125+ let old_id = $self. cx. current_expansion. lint_node_id;
1126+ if $self. monotonic {
1127+ debug_assert_eq!( * $id, ast:: DUMMY_NODE_ID ) ;
1128+ let new_id = $self. cx. resolver. next_node_id( ) ;
1129+ * $id = new_id;
1130+ $self. cx. current_expansion. lint_node_id = new_id;
1131+ }
1132+ let ret = ( $closure) ( ) ;
1133+ $self. cx. current_expansion. lint_node_id = old_id;
1134+ ret
1135+ } } ;
1136+ }
1137+
11011138impl < ' a , ' b > MutVisitor for InvocationCollector < ' a , ' b > {
11021139 fn visit_expr ( & mut self , expr : & mut P < ast:: Expr > ) {
11031140 self . cfg . configure_expr ( expr) ;
@@ -1118,12 +1155,19 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
11181155 self . check_attributes ( & expr. attrs ) ;
11191156 self . collect_bang ( mac, expr. span , AstFragmentKind :: Expr ) . make_expr ( ) . into_inner ( )
11201157 } else {
1121- ensure_sufficient_stack ( || noop_visit_expr ( & mut expr, self ) ) ;
1158+ assign_id ! ( self , & mut expr. id, || {
1159+ ensure_sufficient_stack( || noop_visit_expr( & mut expr, self ) ) ;
1160+ } ) ;
11221161 expr
11231162 }
11241163 } ) ;
11251164 }
11261165
1166+ // This is needed in order to set `lint_node_id` for `let` statements
1167+ fn visit_local ( & mut self , local : & mut P < Local > ) {
1168+ assign_id ! ( self , & mut local. id, || noop_visit_local( local, self ) ) ;
1169+ }
1170+
11271171 fn flat_map_arm ( & mut self , arm : ast:: Arm ) -> SmallVec < [ ast:: Arm ; 1 ] > {
11281172 let mut arm = configure ! ( self , arm) ;
11291173
@@ -1133,7 +1177,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
11331177 . make_arms ( ) ;
11341178 }
11351179
1136- noop_flat_map_arm ( arm, self )
1180+ assign_id ! ( self , & mut arm . id , || noop_flat_map_arm( arm, self ) )
11371181 }
11381182
11391183 fn flat_map_expr_field ( & mut self , field : ast:: ExprField ) -> SmallVec < [ ast:: ExprField ; 1 ] > {
@@ -1145,7 +1189,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
11451189 . make_expr_fields ( ) ;
11461190 }
11471191
1148- noop_flat_map_expr_field ( field, self )
1192+ assign_id ! ( self , & mut field . id , || noop_flat_map_expr_field( field, self ) )
11491193 }
11501194
11511195 fn flat_map_pat_field ( & mut self , fp : ast:: PatField ) -> SmallVec < [ ast:: PatField ; 1 ] > {
@@ -1157,7 +1201,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
11571201 . make_pat_fields ( ) ;
11581202 }
11591203
1160- noop_flat_map_pat_field ( fp, self )
1204+ assign_id ! ( self , & mut fp . id , || noop_flat_map_pat_field( fp, self ) )
11611205 }
11621206
11631207 fn flat_map_param ( & mut self , p : ast:: Param ) -> SmallVec < [ ast:: Param ; 1 ] > {
@@ -1169,7 +1213,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
11691213 . make_params ( ) ;
11701214 }
11711215
1172- noop_flat_map_param ( p, self )
1216+ assign_id ! ( self , & mut p . id , || noop_flat_map_param( p, self ) )
11731217 }
11741218
11751219 fn flat_map_field_def ( & mut self , sf : ast:: FieldDef ) -> SmallVec < [ ast:: FieldDef ; 1 ] > {
@@ -1181,7 +1225,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
11811225 . make_field_defs ( ) ;
11821226 }
11831227
1184- noop_flat_map_field_def ( sf, self )
1228+ assign_id ! ( self , & mut sf . id , || noop_flat_map_field_def( sf, self ) )
11851229 }
11861230
11871231 fn flat_map_variant ( & mut self , variant : ast:: Variant ) -> SmallVec < [ ast:: Variant ; 1 ] > {
@@ -1193,7 +1237,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
11931237 . make_variants ( ) ;
11941238 }
11951239
1196- noop_flat_map_variant ( variant, self )
1240+ assign_id ! ( self , & mut variant . id , || noop_flat_map_variant( variant, self ) )
11971241 }
11981242
11991243 fn filter_map_expr ( & mut self , expr : P < ast:: Expr > ) -> Option < P < ast:: Expr > > {
@@ -1214,9 +1258,11 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
12141258 . make_opt_expr ( )
12151259 . map ( |expr| expr. into_inner ( ) )
12161260 } else {
1217- Some ( {
1218- noop_visit_expr ( & mut expr, self ) ;
1219- expr
1261+ assign_id ! ( self , & mut expr. id, || {
1262+ Some ( {
1263+ noop_visit_expr( & mut expr, self ) ;
1264+ expr
1265+ } )
12201266 } )
12211267 }
12221268 } )
@@ -1266,6 +1312,8 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
12661312 }
12671313
12681314 // The placeholder expander gives ids to statements, so we avoid folding the id here.
1315+ // We don't use `assign_id!` - it will be called when we visit statement's contents
1316+ // (e.g. an expression, item, or local)
12691317 let ast:: Stmt { id, kind, span } = stmt;
12701318 noop_flat_map_stmt_kind ( kind, self )
12711319 . into_iter ( )
@@ -1377,7 +1425,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
13771425 let orig_dir_ownership =
13781426 mem:: replace ( & mut self . cx . current_expansion . dir_ownership , dir_ownership) ;
13791427
1380- let result = noop_flat_map_item ( item, self ) ;
1428+ let result = assign_id ! ( self , & mut item . id , || noop_flat_map_item( item, self ) ) ;
13811429
13821430 // Restore the module info.
13831431 self . cx . current_expansion . dir_ownership = orig_dir_ownership;
@@ -1387,7 +1435,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
13871435 }
13881436 _ => {
13891437 item. attrs = attrs;
1390- noop_flat_map_item ( item, self )
1438+ // The crate root is special - don't assign an ID to it.
1439+ if !( matches ! ( item. kind, ast:: ItemKind :: Mod ( ..) ) && ident == Ident :: invalid ( ) ) {
1440+ assign_id ! ( self , & mut item. id, || noop_flat_map_item( item, self ) )
1441+ } else {
1442+ noop_flat_map_item ( item, self )
1443+ }
13911444 }
13921445 }
13931446 }
@@ -1411,7 +1464,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
14111464 _ => unreachable ! ( ) ,
14121465 } )
14131466 }
1414- _ => noop_flat_map_assoc_item ( item, self ) ,
1467+ _ => {
1468+ assign_id ! ( self , & mut item. id, || noop_flat_map_assoc_item( item, self ) )
1469+ }
14151470 }
14161471 }
14171472
@@ -1434,7 +1489,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
14341489 _ => unreachable ! ( ) ,
14351490 } )
14361491 }
1437- _ => noop_flat_map_assoc_item ( item, self ) ,
1492+ _ => {
1493+ assign_id ! ( self , & mut item. id, || noop_flat_map_assoc_item( item, self ) )
1494+ }
14381495 }
14391496 }
14401497
@@ -1478,7 +1535,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
14781535 _ => unreachable ! ( ) ,
14791536 } )
14801537 }
1481- _ => noop_flat_map_foreign_item ( foreign_item, self ) ,
1538+ _ => {
1539+ assign_id ! ( self , & mut foreign_item. id, || noop_flat_map_foreign_item(
1540+ foreign_item,
1541+ self
1542+ ) )
1543+ }
14821544 }
14831545 }
14841546
@@ -1498,13 +1560,14 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
14981560 . make_generic_params ( ) ;
14991561 }
15001562
1501- noop_flat_map_generic_param ( param, self )
1563+ assign_id ! ( self , & mut param . id , || noop_flat_map_generic_param( param, self ) )
15021564 }
15031565
15041566 fn visit_id ( & mut self , id : & mut ast:: NodeId ) {
1505- if self . monotonic {
1506- debug_assert_eq ! ( * id, ast:: DUMMY_NODE_ID ) ;
1507- * id = self . cx . resolver . next_node_id ( )
1567+ // We may have already assigned a `NodeId`
1568+ // by calling `assign_id`
1569+ if self . monotonic && * id == ast:: DUMMY_NODE_ID {
1570+ * id = self . cx . resolver . next_node_id ( ) ;
15081571 }
15091572 }
15101573}
0 commit comments