@@ -27,6 +27,8 @@ use rustc_serialize::{Decoder, Decodable, Encoder, Encodable};
27
27
use session:: { config, early_error, Session } ;
28
28
use ty:: { self , TyCtxt , Ty } ;
29
29
use ty:: layout:: { LayoutError , LayoutOf , TyLayout } ;
30
+ use ty:: query:: { Providers , queries} ;
31
+
30
32
use util:: nodemap:: FxHashMap ;
31
33
use util:: common:: time;
32
34
@@ -36,10 +38,12 @@ use syntax::edition;
36
38
use syntax_pos:: { MultiSpan , Span , symbol:: { LocalInternedString , Symbol } } ;
37
39
use errors:: DiagnosticBuilder ;
38
40
use hir;
41
+ use hir:: def_id:: DefId ;
39
42
use hir:: def_id:: LOCAL_CRATE ;
40
43
use hir:: intravisit as hir_visit;
41
44
use syntax:: util:: lev_distance:: find_best_match_for_name;
42
45
use syntax:: visit as ast_visit;
46
+ use syntax:: ast:: { NodeId , CRATE_NODE_ID } ;
43
47
44
48
/// Information about the registered lints.
45
49
///
@@ -55,6 +59,7 @@ pub struct LintStore {
55
59
pre_expansion_passes : Option < Vec < EarlyLintPassObject > > ,
56
60
early_passes : Option < Vec < EarlyLintPassObject > > ,
57
61
late_passes : Option < Vec < LateLintPassObject > > ,
62
+ late_module_passes : Option < Vec < LateLintPassObject > > ,
58
63
59
64
/// Lints indexed by name.
60
65
by_name : FxHashMap < String , TargetLint > ,
@@ -150,6 +155,7 @@ impl LintStore {
150
155
pre_expansion_passes : Some ( vec ! [ ] ) ,
151
156
early_passes : Some ( vec ! [ ] ) ,
152
157
late_passes : Some ( vec ! [ ] ) ,
158
+ late_module_passes : Some ( vec ! [ ] ) ,
153
159
by_name : Default :: default ( ) ,
154
160
future_incompatible : Default :: default ( ) ,
155
161
lint_groups : Default :: default ( ) ,
@@ -199,9 +205,14 @@ impl LintStore {
199
205
pub fn register_late_pass ( & mut self ,
200
206
sess : Option < & Session > ,
201
207
from_plugin : bool ,
208
+ per_module : bool ,
202
209
pass : LateLintPassObject ) {
203
210
self . push_pass ( sess, from_plugin, & pass) ;
204
- self . late_passes . as_mut ( ) . unwrap ( ) . push ( pass) ;
211
+ if per_module {
212
+ self . late_module_passes . as_mut ( ) . unwrap ( ) . push ( pass) ;
213
+ } else {
214
+ self . late_passes . as_mut ( ) . unwrap ( ) . push ( pass) ;
215
+ }
205
216
}
206
217
207
218
// Helper method for register_early/late_pass
@@ -508,6 +519,7 @@ pub struct LateContext<'a, 'tcx: 'a> {
508
519
pub tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
509
520
510
521
/// Side-tables for the body we are in.
522
+ // FIXME: Make this lazy to avoid running the TypeckTables query?
511
523
pub tables : & ' a ty:: TypeckTables < ' tcx > ,
512
524
513
525
/// Parameter environment for the item we are in.
@@ -523,6 +535,9 @@ pub struct LateContext<'a, 'tcx: 'a> {
523
535
524
536
/// Generic type parameters in scope for the item we are in.
525
537
pub generics : Option < & ' tcx hir:: Generics > ,
538
+
539
+ /// We are only looking at one module
540
+ only_module : bool ,
526
541
}
527
542
528
543
/// Context for lint checking of the AST, after expansion, before lowering to
@@ -801,6 +816,12 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> {
801
816
pub fn current_lint_root ( & self ) -> ast:: NodeId {
802
817
self . last_ast_node_with_lint_attrs
803
818
}
819
+
820
+ fn process_mod ( & mut self , m : & ' tcx hir:: Mod , s : Span , n : ast:: NodeId ) {
821
+ run_lints ! ( self , check_mod, m, s, n) ;
822
+ hir_visit:: walk_mod ( self , m, n) ;
823
+ run_lints ! ( self , check_mod_post, m, s, n) ;
824
+ }
804
825
}
805
826
806
827
impl < ' a , ' tcx > LayoutOf for LateContext < ' a , ' tcx > {
@@ -932,9 +953,9 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> {
932
953
}
933
954
934
955
fn visit_mod ( & mut self , m : & ' tcx hir:: Mod , s : Span , n : ast:: NodeId ) {
935
- run_lints ! ( self , check_mod , m , s , n ) ;
936
- hir_visit :: walk_mod ( self , m , n) ;
937
- run_lints ! ( self , check_mod_post , m , s , n ) ;
956
+ if ! self . only_module {
957
+ self . process_mod ( m , s , n) ;
958
+ }
938
959
}
939
960
940
961
fn visit_local ( & mut self , l : & ' tcx hir:: Local ) {
@@ -1199,11 +1220,65 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
1199
1220
}
1200
1221
}
1201
1222
1223
+ pub fn lint_mod < ' tcx > ( tcx : TyCtxt < ' _ , ' tcx , ' tcx > , module_def_id : DefId ) {
1224
+ fn find_last_node_with_lint_attrs < ' tcx > (
1225
+ tcx : TyCtxt < ' _ , ' tcx , ' tcx > ,
1226
+ mut id : NodeId
1227
+ ) -> NodeId {
1228
+ let sets = tcx. lint_levels ( LOCAL_CRATE ) ;
1229
+ loop {
1230
+ let hir_id = tcx. hir ( ) . node_to_hir_id ( id) ;
1231
+ if sets. lint_level_set ( hir_id) . is_some ( ) {
1232
+ return id
1233
+ }
1234
+ let next = tcx. hir ( ) . get_parent_node ( id) ;
1235
+ if next == id {
1236
+ return CRATE_NODE_ID ;
1237
+ }
1238
+ id = next;
1239
+ }
1240
+ }
1202
1241
1203
- /// Perform lint checking on a crate.
1204
- ///
1205
- /// Consumes the `lint_store` field of the `Session`.
1206
- pub fn check_crate < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ) {
1242
+ // Restricts this to only items in this module
1243
+ let access_levels = & tcx. privacy_access_levels ( LOCAL_CRATE ) ;
1244
+
1245
+ let store = & tcx. sess . lint_store ;
1246
+ let passes = store. borrow_mut ( ) . late_module_passes . take ( ) ;
1247
+
1248
+ let mut cx = LateContext {
1249
+ tcx,
1250
+ tables : & ty:: TypeckTables :: empty ( None ) ,
1251
+ param_env : ty:: ParamEnv :: empty ( ) ,
1252
+ access_levels,
1253
+ lint_sess : LintSession {
1254
+ lints : store. borrow ( ) ,
1255
+ passes,
1256
+ } ,
1257
+ last_ast_node_with_lint_attrs : find_last_node_with_lint_attrs (
1258
+ tcx,
1259
+ tcx. hir ( ) . as_local_node_id ( module_def_id) . unwrap ( ) ,
1260
+ ) ,
1261
+ generics : None ,
1262
+ only_module : true ,
1263
+ } ;
1264
+
1265
+ let ( module, span, node_id) = tcx. hir ( ) . get_module ( module_def_id) ;
1266
+ cx. process_mod ( module, span, node_id) ;
1267
+
1268
+ // Put the lint store levels and passes back in the session.
1269
+ let passes = cx. lint_sess . passes ;
1270
+ drop ( cx. lint_sess . lints ) ;
1271
+ store. borrow_mut ( ) . late_module_passes = passes;
1272
+ }
1273
+
1274
+ pub ( crate ) fn provide ( providers : & mut Providers < ' _ > ) {
1275
+ * providers = Providers {
1276
+ lint_mod,
1277
+ ..* providers
1278
+ } ;
1279
+ }
1280
+
1281
+ fn lint_crate < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ) {
1207
1282
let access_levels = & tcx. privacy_access_levels ( LOCAL_CRATE ) ;
1208
1283
1209
1284
let krate = tcx. hir ( ) . krate ( ) ;
@@ -1221,6 +1296,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
1221
1296
} ,
1222
1297
last_ast_node_with_lint_attrs : ast:: CRATE_NODE_ID ,
1223
1298
generics : None ,
1299
+ only_module : false ,
1224
1300
} ;
1225
1301
1226
1302
// Visit the whole crate.
@@ -1240,6 +1316,17 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
1240
1316
tcx. sess . lint_store . borrow_mut ( ) . late_passes = passes;
1241
1317
}
1242
1318
1319
+ /// Perform lint checking on a crate.
1320
+ pub fn check_crate < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ) {
1321
+ // Run per-module lints
1322
+ for & module in tcx. hir ( ) . krate ( ) . modules . keys ( ) {
1323
+ queries:: lint_mod:: ensure ( tcx, tcx. hir ( ) . local_def_id ( module) ) ;
1324
+ }
1325
+
1326
+ // Run whole crate non-incremental lints
1327
+ lint_crate ( tcx) ;
1328
+ }
1329
+
1243
1330
struct EarlyLintPassObjects < ' a > {
1244
1331
lints : & ' a mut [ EarlyLintPassObject ] ,
1245
1332
}
0 commit comments