@@ -12,7 +12,7 @@ use rustc_ast::ptr::P;
12
12
use rustc_ast:: token;
13
13
use rustc_ast:: tokenstream:: TokenStream ;
14
14
use 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 } ;
16
16
use rustc_ast:: { MacCallStmt , MacStmtStyle , MetaItemKind , ModKind , NestedMetaItem } ;
17
17
use rustc_ast:: { NodeId , PatKind , Path , StmtKind , Unsafe } ;
18
18
use rustc_ast_pretty:: pprust;
@@ -1098,6 +1098,43 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
1098
1098
}
1099
1099
}
1100
1100
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
+
1101
1138
impl < ' a , ' b > MutVisitor for InvocationCollector < ' a , ' b > {
1102
1139
fn visit_expr ( & mut self , expr : & mut P < ast:: Expr > ) {
1103
1140
self . cfg . configure_expr ( expr) ;
@@ -1118,12 +1155,19 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
1118
1155
self . check_attributes ( & expr. attrs ) ;
1119
1156
self . collect_bang ( mac, expr. span , AstFragmentKind :: Expr ) . make_expr ( ) . into_inner ( )
1120
1157
} 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
+ } ) ;
1122
1161
expr
1123
1162
}
1124
1163
} ) ;
1125
1164
}
1126
1165
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
+
1127
1171
fn flat_map_arm ( & mut self , arm : ast:: Arm ) -> SmallVec < [ ast:: Arm ; 1 ] > {
1128
1172
let mut arm = configure ! ( self , arm) ;
1129
1173
@@ -1133,7 +1177,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
1133
1177
. make_arms ( ) ;
1134
1178
}
1135
1179
1136
- noop_flat_map_arm ( arm, self )
1180
+ assign_id ! ( self , & mut arm . id , || noop_flat_map_arm( arm, self ) )
1137
1181
}
1138
1182
1139
1183
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> {
1145
1189
. make_expr_fields ( ) ;
1146
1190
}
1147
1191
1148
- noop_flat_map_expr_field ( field, self )
1192
+ assign_id ! ( self , & mut field . id , || noop_flat_map_expr_field( field, self ) )
1149
1193
}
1150
1194
1151
1195
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> {
1157
1201
. make_pat_fields ( ) ;
1158
1202
}
1159
1203
1160
- noop_flat_map_pat_field ( fp, self )
1204
+ assign_id ! ( self , & mut fp . id , || noop_flat_map_pat_field( fp, self ) )
1161
1205
}
1162
1206
1163
1207
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> {
1169
1213
. make_params ( ) ;
1170
1214
}
1171
1215
1172
- noop_flat_map_param ( p, self )
1216
+ assign_id ! ( self , & mut p . id , || noop_flat_map_param( p, self ) )
1173
1217
}
1174
1218
1175
1219
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> {
1181
1225
. make_field_defs ( ) ;
1182
1226
}
1183
1227
1184
- noop_flat_map_field_def ( sf, self )
1228
+ assign_id ! ( self , & mut sf . id , || noop_flat_map_field_def( sf, self ) )
1185
1229
}
1186
1230
1187
1231
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> {
1193
1237
. make_variants ( ) ;
1194
1238
}
1195
1239
1196
- noop_flat_map_variant ( variant, self )
1240
+ assign_id ! ( self , & mut variant . id , || noop_flat_map_variant( variant, self ) )
1197
1241
}
1198
1242
1199
1243
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> {
1214
1258
. make_opt_expr ( )
1215
1259
. map ( |expr| expr. into_inner ( ) )
1216
1260
} 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
+ } )
1220
1266
} )
1221
1267
}
1222
1268
} )
@@ -1266,6 +1312,8 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
1266
1312
}
1267
1313
1268
1314
// 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)
1269
1317
let ast:: Stmt { id, kind, span } = stmt;
1270
1318
noop_flat_map_stmt_kind ( kind, self )
1271
1319
. into_iter ( )
@@ -1377,7 +1425,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
1377
1425
let orig_dir_ownership =
1378
1426
mem:: replace ( & mut self . cx . current_expansion . dir_ownership , dir_ownership) ;
1379
1427
1380
- let result = noop_flat_map_item ( item, self ) ;
1428
+ let result = assign_id ! ( self , & mut item . id , || noop_flat_map_item( item, self ) ) ;
1381
1429
1382
1430
// Restore the module info.
1383
1431
self . cx . current_expansion . dir_ownership = orig_dir_ownership;
@@ -1387,7 +1435,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
1387
1435
}
1388
1436
_ => {
1389
1437
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
+ }
1391
1444
}
1392
1445
}
1393
1446
}
@@ -1411,7 +1464,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
1411
1464
_ => unreachable ! ( ) ,
1412
1465
} )
1413
1466
}
1414
- _ => noop_flat_map_assoc_item ( item, self ) ,
1467
+ _ => {
1468
+ assign_id ! ( self , & mut item. id, || noop_flat_map_assoc_item( item, self ) )
1469
+ }
1415
1470
}
1416
1471
}
1417
1472
@@ -1434,7 +1489,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
1434
1489
_ => unreachable ! ( ) ,
1435
1490
} )
1436
1491
}
1437
- _ => noop_flat_map_assoc_item ( item, self ) ,
1492
+ _ => {
1493
+ assign_id ! ( self , & mut item. id, || noop_flat_map_assoc_item( item, self ) )
1494
+ }
1438
1495
}
1439
1496
}
1440
1497
@@ -1478,7 +1535,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
1478
1535
_ => unreachable ! ( ) ,
1479
1536
} )
1480
1537
}
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
+ }
1482
1544
}
1483
1545
}
1484
1546
@@ -1498,13 +1560,14 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
1498
1560
. make_generic_params ( ) ;
1499
1561
}
1500
1562
1501
- noop_flat_map_generic_param ( param, self )
1563
+ assign_id ! ( self , & mut param . id , || noop_flat_map_generic_param( param, self ) )
1502
1564
}
1503
1565
1504
1566
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 ( ) ;
1508
1571
}
1509
1572
}
1510
1573
}
0 commit comments