@@ -27,6 +27,7 @@ use crate::rustc_serialize::{Decoder, Decodable, Encoder, Encodable};
27
27
use crate :: session:: { config, early_error, Session } ;
28
28
use crate :: ty:: { self , TyCtxt , Ty } ;
29
29
use crate :: ty:: layout:: { LayoutError , LayoutOf , TyLayout } ;
30
+ use crate :: ty:: query:: Providers ;
30
31
use crate :: util:: nodemap:: FxHashMap ;
31
32
use crate :: util:: common:: time;
32
33
@@ -36,8 +37,9 @@ use syntax::edition;
36
37
use syntax_pos:: { MultiSpan , Span , symbol:: { LocalInternedString , Symbol } } ;
37
38
use errors:: DiagnosticBuilder ;
38
39
use crate :: hir;
39
- use crate :: hir:: def_id:: LOCAL_CRATE ;
40
+ use crate :: hir:: def_id:: { DefId , LOCAL_CRATE } ;
40
41
use crate :: hir:: intravisit as hir_visit;
42
+ use crate :: hir:: intravisit:: Visitor ;
41
43
use syntax:: util:: lev_distance:: find_best_match_for_name;
42
44
use syntax:: visit as ast_visit;
43
45
@@ -55,6 +57,7 @@ pub struct LintStore {
55
57
pre_expansion_passes : Option < Vec < EarlyLintPassObject > > ,
56
58
early_passes : Option < Vec < EarlyLintPassObject > > ,
57
59
late_passes : Option < Vec < LateLintPassObject > > ,
60
+ late_module_passes : Option < Vec < LateLintPassObject > > ,
58
61
59
62
/// Lints indexed by name.
60
63
by_name : FxHashMap < String , TargetLint > ,
@@ -150,6 +153,7 @@ impl LintStore {
150
153
pre_expansion_passes : Some ( vec ! [ ] ) ,
151
154
early_passes : Some ( vec ! [ ] ) ,
152
155
late_passes : Some ( vec ! [ ] ) ,
156
+ late_module_passes : Some ( vec ! [ ] ) ,
153
157
by_name : Default :: default ( ) ,
154
158
future_incompatible : Default :: default ( ) ,
155
159
lint_groups : Default :: default ( ) ,
@@ -199,9 +203,14 @@ impl LintStore {
199
203
pub fn register_late_pass ( & mut self ,
200
204
sess : Option < & Session > ,
201
205
from_plugin : bool ,
206
+ per_module : bool ,
202
207
pass : LateLintPassObject ) {
203
208
self . push_pass ( sess, from_plugin, & pass) ;
204
- self . late_passes . as_mut ( ) . unwrap ( ) . push ( pass) ;
209
+ if per_module {
210
+ self . late_module_passes . as_mut ( ) . unwrap ( ) . push ( pass) ;
211
+ } else {
212
+ self . late_passes . as_mut ( ) . unwrap ( ) . push ( pass) ;
213
+ }
205
214
}
206
215
207
216
// Helper method for register_early/late_pass
@@ -508,6 +517,7 @@ pub struct LateContext<'a, 'tcx: 'a> {
508
517
pub tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
509
518
510
519
/// Side-tables for the body we are in.
520
+ // FIXME: Make this lazy to avoid running the TypeckTables query?
511
521
pub tables : & ' a ty:: TypeckTables < ' tcx > ,
512
522
513
523
/// Parameter environment for the item we are in.
@@ -523,6 +533,9 @@ pub struct LateContext<'a, 'tcx: 'a> {
523
533
524
534
/// Generic type parameters in scope for the item we are in.
525
535
pub generics : Option < & ' tcx hir:: Generics > ,
536
+
537
+ /// We are only looking at one module
538
+ only_module : bool ,
526
539
}
527
540
528
541
/// Context for lint checking of the AST, after expansion, before lowering to
@@ -803,6 +816,12 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> {
803
816
pub fn current_lint_root ( & self ) -> hir:: HirId {
804
817
self . last_node_with_lint_attrs
805
818
}
819
+
820
+ fn process_mod ( & mut self , m : & ' tcx hir:: Mod , s : Span , n : hir:: HirId ) {
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
+ }
806
825
}
807
826
808
827
impl < ' a , ' tcx > LayoutOf for LateContext < ' a , ' tcx > {
@@ -934,9 +953,9 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> {
934
953
}
935
954
936
955
fn visit_mod ( & mut self , m : & ' tcx hir:: Mod , s : Span , n : hir:: HirId ) {
937
- run_lints ! ( self , check_mod , m , s , n ) ;
938
- hir_visit :: walk_mod ( self , m , n) ;
939
- run_lints ! ( self , check_mod_post , m , s , n ) ;
956
+ if ! self . only_module {
957
+ self . process_mod ( m , s , n) ;
958
+ }
940
959
}
941
960
942
961
fn visit_local ( & mut self , l : & ' tcx hir:: Local ) {
@@ -1203,11 +1222,48 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
1203
1222
}
1204
1223
}
1205
1224
1225
+ pub fn lint_mod < ' tcx > ( tcx : TyCtxt < ' _ , ' tcx , ' tcx > , module_def_id : DefId ) {
1226
+ let access_levels = & tcx. privacy_access_levels ( LOCAL_CRATE ) ;
1206
1227
1207
- /// Performs lint checking on a crate.
1208
- ///
1209
- /// Consumes the `lint_store` field of the `Session`.
1210
- pub fn check_crate < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ) {
1228
+ let store = & tcx. sess . lint_store ;
1229
+ let passes = store. borrow_mut ( ) . late_module_passes . take ( ) ;
1230
+
1231
+ let mut cx = LateContext {
1232
+ tcx,
1233
+ tables : & ty:: TypeckTables :: empty ( None ) ,
1234
+ param_env : ty:: ParamEnv :: empty ( ) ,
1235
+ access_levels,
1236
+ lint_sess : LintSession {
1237
+ lints : store. borrow ( ) ,
1238
+ passes,
1239
+ } ,
1240
+ last_node_with_lint_attrs : tcx. hir ( ) . as_local_hir_id ( module_def_id) . unwrap ( ) ,
1241
+ generics : None ,
1242
+ only_module : true ,
1243
+ } ;
1244
+
1245
+ let ( module, span, hir_id) = tcx. hir ( ) . get_module ( module_def_id) ;
1246
+ cx. process_mod ( module, span, hir_id) ;
1247
+
1248
+ // Visit the crate attributes
1249
+ if hir_id == hir:: CRATE_HIR_ID {
1250
+ walk_list ! ( cx, visit_attribute, cx. tcx. hir( ) . attrs_by_hir_id( hir:: CRATE_HIR_ID ) ) ;
1251
+ }
1252
+
1253
+ // Put the lint store levels and passes back in the session.
1254
+ let passes = cx. lint_sess . passes ;
1255
+ drop ( cx. lint_sess . lints ) ;
1256
+ store. borrow_mut ( ) . late_module_passes = passes;
1257
+ }
1258
+
1259
+ pub ( crate ) fn provide ( providers : & mut Providers < ' _ > ) {
1260
+ * providers = Providers {
1261
+ lint_mod,
1262
+ ..* providers
1263
+ } ;
1264
+ }
1265
+
1266
+ fn lint_crate < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ) {
1211
1267
let access_levels = & tcx. privacy_access_levels ( LOCAL_CRATE ) ;
1212
1268
1213
1269
let krate = tcx. hir ( ) . krate ( ) ;
@@ -1225,6 +1281,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
1225
1281
} ,
1226
1282
last_node_with_lint_attrs : hir:: CRATE_HIR_ID ,
1227
1283
generics : None ,
1284
+ only_module : false ,
1228
1285
} ;
1229
1286
1230
1287
// Visit the whole crate.
@@ -1244,6 +1301,17 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
1244
1301
tcx. sess . lint_store . borrow_mut ( ) . late_passes = passes;
1245
1302
}
1246
1303
1304
+ /// Performs lint checking on a crate.
1305
+ pub fn check_crate < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ) {
1306
+ // Run per-module lints
1307
+ for & module in tcx. hir ( ) . krate ( ) . modules . keys ( ) {
1308
+ tcx. ensure ( ) . lint_mod ( tcx. hir ( ) . local_def_id ( module) ) ;
1309
+ }
1310
+
1311
+ // Run whole crate non-incremental lints
1312
+ lint_crate ( tcx) ;
1313
+ }
1314
+
1247
1315
struct EarlyLintPassObjects < ' a > {
1248
1316
lints : & ' a mut [ EarlyLintPassObject ] ,
1249
1317
}
0 commit comments