@@ -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
32
34
use std:: default:: Default as StdDefault ;
@@ -35,6 +37,7 @@ use syntax::edition;
35
37
use syntax_pos:: { MultiSpan , Span , symbol:: { LocalInternedString , Symbol } } ;
36
38
use errors:: DiagnosticBuilder ;
37
39
use hir;
40
+ use hir:: def_id:: DefId ;
38
41
use hir:: def_id:: LOCAL_CRATE ;
39
42
use hir:: intravisit as hir_visit;
40
43
use syntax:: util:: lev_distance:: find_best_match_for_name;
@@ -54,6 +57,7 @@ pub struct LintStore {
54
57
pre_expansion_passes : Option < Vec < EarlyLintPassObject > > ,
55
58
early_passes : Option < Vec < EarlyLintPassObject > > ,
56
59
late_passes : Option < Vec < LateLintPassObject > > ,
60
+ late_module_passes : Option < Vec < LateLintPassObject > > ,
57
61
58
62
/// Lints indexed by name.
59
63
by_name : FxHashMap < String , TargetLint > ,
@@ -150,6 +154,7 @@ impl LintStore {
150
154
pre_expansion_passes : Some ( vec ! [ ] ) ,
151
155
early_passes : Some ( vec ! [ ] ) ,
152
156
late_passes : Some ( vec ! [ ] ) ,
157
+ late_module_passes : Some ( vec ! [ ] ) ,
153
158
by_name : Default :: default ( ) ,
154
159
future_incompatible : Default :: default ( ) ,
155
160
lint_groups : Default :: default ( ) ,
@@ -192,9 +197,14 @@ impl LintStore {
192
197
pub fn register_late_pass ( & mut self ,
193
198
sess : Option < & Session > ,
194
199
from_plugin : bool ,
200
+ per_module : bool ,
195
201
pass : LateLintPassObject ) {
196
202
self . push_pass ( sess, from_plugin, & pass) ;
197
- self . late_passes . as_mut ( ) . unwrap ( ) . push ( pass) ;
203
+ if per_module {
204
+ self . late_module_passes . as_mut ( ) . unwrap ( ) . push ( pass) ;
205
+ } else {
206
+ self . late_passes . as_mut ( ) . unwrap ( ) . push ( pass) ;
207
+ }
198
208
}
199
209
200
210
// Helper method for register_early/late_pass
@@ -501,6 +511,7 @@ pub struct LateContext<'a, 'tcx: 'a> {
501
511
pub tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
502
512
503
513
/// Side-tables for the body we are in.
514
+ // FIXME: Make this lazy to avoid running the TypeckTables query?
504
515
pub tables : & ' a ty:: TypeckTables < ' tcx > ,
505
516
506
517
/// Parameter environment for the item we are in.
@@ -516,6 +527,9 @@ pub struct LateContext<'a, 'tcx: 'a> {
516
527
517
528
/// Generic type parameters in scope for the item we are in.
518
529
pub generics : Option < & ' tcx hir:: Generics > ,
530
+
531
+ /// We are only looking at one module
532
+ only_module : bool ,
519
533
}
520
534
521
535
/// Context for lint checking of the AST, after expansion, before lowering to
@@ -787,6 +801,12 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> {
787
801
pub fn current_lint_root ( & self ) -> ast:: NodeId {
788
802
self . last_ast_node_with_lint_attrs
789
803
}
804
+
805
+ fn process_mod ( & mut self , m : & ' tcx hir:: Mod , s : Span , n : ast:: NodeId ) {
806
+ run_lints ! ( self , check_mod, m, s, n) ;
807
+ hir_visit:: walk_mod ( self , m, n) ;
808
+ run_lints ! ( self , check_mod_post, m, s, n) ;
809
+ }
790
810
}
791
811
792
812
impl < ' a , ' tcx > LayoutOf for LateContext < ' a , ' tcx > {
@@ -918,9 +938,9 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> {
918
938
}
919
939
920
940
fn visit_mod ( & mut self , m : & ' tcx hir:: Mod , s : Span , n : ast:: NodeId ) {
921
- run_lints ! ( self , check_mod , m , s , n ) ;
922
- hir_visit :: walk_mod ( self , m , n) ;
923
- run_lints ! ( self , check_mod_post , m , s , n ) ;
941
+ if ! self . only_module {
942
+ self . process_mod ( m , s , n) ;
943
+ }
924
944
}
925
945
926
946
fn visit_local ( & mut self , l : & ' tcx hir:: Local ) {
@@ -1191,6 +1211,50 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> {
1191
1211
}
1192
1212
1193
1213
1214
+ pub fn lint_mod < ' tcx > ( tcx : TyCtxt < ' _ , ' tcx , ' tcx > , module_def_id : DefId ) {
1215
+ // Look for the parents of the module and for attributes on them
1216
+ // to populate last_ast_node_with_lint_attrs
1217
+
1218
+ // Restricts this to only items in this module
1219
+ let access_levels = & tcx. privacy_access_levels ( LOCAL_CRATE ) ;
1220
+
1221
+ let store = & tcx. sess . lint_store ;
1222
+ let passes = store. borrow_mut ( ) . late_module_passes . take ( ) ;
1223
+
1224
+ let mut cx = LateContext {
1225
+ tcx,
1226
+ tables : & ty:: TypeckTables :: empty ( None ) ,
1227
+ param_env : ty:: ParamEnv :: empty ( ) ,
1228
+ access_levels,
1229
+ lint_sess : LintSession {
1230
+ lints : store. borrow ( ) ,
1231
+ passes,
1232
+ } ,
1233
+ // Invalid for modules.
1234
+ // FIXME: Have the modules require the parent module's attribute
1235
+ last_ast_node_with_lint_attrs : ast:: CRATE_NODE_ID ,
1236
+
1237
+ generics : None ,
1238
+
1239
+ only_module : true ,
1240
+ } ;
1241
+
1242
+ let ( module, span, node_id) = tcx. hir ( ) . get_module ( module_def_id) ;
1243
+ cx. process_mod ( module, span, node_id) ;
1244
+
1245
+ // Put the lint store levels and passes back in the session.
1246
+ let passes = cx. lint_sess . passes ;
1247
+ drop ( cx. lint_sess . lints ) ;
1248
+ store. borrow_mut ( ) . late_module_passes = passes;
1249
+ }
1250
+
1251
+ pub ( crate ) fn provide ( providers : & mut Providers < ' _ > ) {
1252
+ * providers = Providers {
1253
+ lint_mod,
1254
+ ..* providers
1255
+ } ;
1256
+ }
1257
+
1194
1258
/// Perform lint checking on a crate.
1195
1259
///
1196
1260
/// Consumes the `lint_store` field of the `Session`.
@@ -1212,6 +1276,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
1212
1276
} ,
1213
1277
last_ast_node_with_lint_attrs : ast:: CRATE_NODE_ID ,
1214
1278
generics : None ,
1279
+ only_module : false ,
1215
1280
} ;
1216
1281
1217
1282
// Visit the whole crate.
@@ -1229,6 +1294,11 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
1229
1294
1230
1295
// Put the lint store levels and passes back in the session.
1231
1296
tcx. sess . lint_store . borrow_mut ( ) . late_passes = passes;
1297
+
1298
+ // Run per-module lints
1299
+ for & module in tcx. hir ( ) . krate ( ) . modules . keys ( ) {
1300
+ queries:: lint_mod:: ensure ( tcx, tcx. hir ( ) . local_def_id ( module) ) ;
1301
+ }
1232
1302
}
1233
1303
1234
1304
pub fn check_ast_crate (
0 commit comments