@@ -27,6 +27,7 @@ use crate::rustc_serialize::{Decoder, Decodable, Encoder, Encodable};
2727use crate :: session:: { config, early_error, Session } ;
2828use crate :: ty:: { self , TyCtxt , Ty } ;
2929use crate :: ty:: layout:: { LayoutError , LayoutOf , TyLayout } ;
30+ use crate :: ty:: query:: Providers ;
3031use crate :: util:: nodemap:: FxHashMap ;
3132use crate :: util:: common:: time;
3233
@@ -36,7 +37,7 @@ use syntax::edition;
3637use syntax_pos:: { MultiSpan , Span , symbol:: { LocalInternedString , Symbol } } ;
3738use errors:: DiagnosticBuilder ;
3839use crate :: hir;
39- use crate :: hir:: def_id:: LOCAL_CRATE ;
40+ use crate :: hir:: def_id:: { DefId , LOCAL_CRATE } ;
4041use crate :: hir:: intravisit as hir_visit;
4142use syntax:: util:: lev_distance:: find_best_match_for_name;
4243use syntax:: visit as ast_visit;
@@ -55,6 +56,7 @@ pub struct LintStore {
5556 pre_expansion_passes : Option < Vec < EarlyLintPassObject > > ,
5657 early_passes : Option < Vec < EarlyLintPassObject > > ,
5758 late_passes : Option < Vec < LateLintPassObject > > ,
59+ late_module_passes : Option < Vec < LateLintPassObject > > ,
5860
5961 /// Lints indexed by name.
6062 by_name : FxHashMap < String , TargetLint > ,
@@ -150,6 +152,7 @@ impl LintStore {
150152 pre_expansion_passes : Some ( vec ! [ ] ) ,
151153 early_passes : Some ( vec ! [ ] ) ,
152154 late_passes : Some ( vec ! [ ] ) ,
155+ late_module_passes : Some ( vec ! [ ] ) ,
153156 by_name : Default :: default ( ) ,
154157 future_incompatible : Default :: default ( ) ,
155158 lint_groups : Default :: default ( ) ,
@@ -199,9 +202,14 @@ impl LintStore {
199202 pub fn register_late_pass ( & mut self ,
200203 sess : Option < & Session > ,
201204 from_plugin : bool ,
205+ per_module : bool ,
202206 pass : LateLintPassObject ) {
203207 self . push_pass ( sess, from_plugin, & pass) ;
204- self . late_passes . as_mut ( ) . unwrap ( ) . push ( pass) ;
208+ if per_module {
209+ self . late_module_passes . as_mut ( ) . unwrap ( ) . push ( pass) ;
210+ } else {
211+ self . late_passes . as_mut ( ) . unwrap ( ) . push ( pass) ;
212+ }
205213 }
206214
207215 // Helper method for register_early/late_pass
@@ -508,6 +516,7 @@ pub struct LateContext<'a, 'tcx: 'a> {
508516 pub tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
509517
510518 /// Side-tables for the body we are in.
519+ // FIXME: Make this lazy to avoid running the TypeckTables query?
511520 pub tables : & ' a ty:: TypeckTables < ' tcx > ,
512521
513522 /// Parameter environment for the item we are in.
@@ -523,6 +532,9 @@ pub struct LateContext<'a, 'tcx: 'a> {
523532
524533 /// Generic type parameters in scope for the item we are in.
525534 pub generics : Option < & ' tcx hir:: Generics > ,
535+
536+ /// We are only looking at one module
537+ only_module : bool ,
526538}
527539
528540/// Context for lint checking of the AST, after expansion, before lowering to
@@ -803,6 +815,12 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> {
803815 pub fn current_lint_root ( & self ) -> hir:: HirId {
804816 self . last_node_with_lint_attrs
805817 }
818+
819+ fn process_mod ( & mut self , m : & ' tcx hir:: Mod , s : Span , n : hir:: HirId ) {
820+ run_lints ! ( self , check_mod, m, s, n) ;
821+ hir_visit:: walk_mod ( self , m, n) ;
822+ run_lints ! ( self , check_mod_post, m, s, n) ;
823+ }
806824}
807825
808826impl < ' a , ' tcx > LayoutOf for LateContext < ' a , ' tcx > {
@@ -934,9 +952,9 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> {
934952 }
935953
936954 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 ) ;
955+ if ! self . only_module {
956+ self . process_mod ( m , s , n) ;
957+ }
940958 }
941959
942960 fn visit_local ( & mut self , l : & ' tcx hir:: Local ) {
@@ -1203,11 +1221,43 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
12031221 }
12041222}
12051223
1224+ pub fn lint_mod < ' tcx > ( tcx : TyCtxt < ' _ , ' tcx , ' tcx > , module_def_id : DefId ) {
1225+ let access_levels = & tcx. privacy_access_levels ( LOCAL_CRATE ) ;
12061226
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 > ) {
1227+ let store = & tcx. sess . lint_store ;
1228+ let passes = store. borrow_mut ( ) . late_module_passes . take ( ) ;
1229+
1230+ let mut cx = LateContext {
1231+ tcx,
1232+ tables : & ty:: TypeckTables :: empty ( None ) ,
1233+ param_env : ty:: ParamEnv :: empty ( ) ,
1234+ access_levels,
1235+ lint_sess : LintSession {
1236+ lints : store. borrow ( ) ,
1237+ passes,
1238+ } ,
1239+ last_node_with_lint_attrs : tcx. hir ( ) . as_local_hir_id ( module_def_id) . unwrap ( ) ,
1240+ generics : None ,
1241+ only_module : true ,
1242+ } ;
1243+
1244+ let ( module, span, hir_id) = tcx. hir ( ) . get_module ( module_def_id) ;
1245+ cx. process_mod ( module, span, hir_id) ;
1246+
1247+ // Put the lint store levels and passes back in the session.
1248+ let passes = cx. lint_sess . passes ;
1249+ drop ( cx. lint_sess . lints ) ;
1250+ store. borrow_mut ( ) . late_module_passes = passes;
1251+ }
1252+
1253+ pub ( crate ) fn provide ( providers : & mut Providers < ' _ > ) {
1254+ * providers = Providers {
1255+ lint_mod,
1256+ ..* providers
1257+ } ;
1258+ }
1259+
1260+ fn lint_crate < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ) {
12111261 let access_levels = & tcx. privacy_access_levels ( LOCAL_CRATE ) ;
12121262
12131263 let krate = tcx. hir ( ) . krate ( ) ;
@@ -1225,6 +1275,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
12251275 } ,
12261276 last_node_with_lint_attrs : hir:: CRATE_HIR_ID ,
12271277 generics : None ,
1278+ only_module : false ,
12281279 } ;
12291280
12301281 // Visit the whole crate.
@@ -1244,6 +1295,17 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
12441295 tcx. sess . lint_store . borrow_mut ( ) . late_passes = passes;
12451296}
12461297
1298+ /// Performs lint checking on a crate.
1299+ pub fn check_crate < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > ) {
1300+ // Run per-module lints
1301+ for & module in tcx. hir ( ) . krate ( ) . modules . keys ( ) {
1302+ tcx. ensure ( ) . lint_mod ( tcx. hir ( ) . local_def_id ( module) ) ;
1303+ }
1304+
1305+ // Run whole crate non-incremental lints
1306+ lint_crate ( tcx) ;
1307+ }
1308+
12471309struct EarlyLintPassObjects < ' a > {
12481310 lints : & ' a mut [ EarlyLintPassObject ] ,
12491311}
0 commit comments