@@ -27,6 +27,8 @@ use rustc_serialize::{Decoder, Decodable, Encoder, Encodable};
2727use  session:: { config,  early_error,  Session } ; 
2828use  ty:: { self ,  TyCtxt ,  Ty } ; 
2929use  ty:: layout:: { LayoutError ,  LayoutOf ,  TyLayout } ; 
30+ use  ty:: query:: { Providers ,  queries} ; 
31+ 
3032use  util:: nodemap:: FxHashMap ; 
3133use  util:: common:: time; 
3234
@@ -36,10 +38,12 @@ use syntax::edition;
3638use  syntax_pos:: { MultiSpan ,  Span ,  symbol:: { LocalInternedString ,  Symbol } } ; 
3739use  errors:: DiagnosticBuilder ; 
3840use  hir; 
41+ use  hir:: def_id:: DefId ; 
3942use  hir:: def_id:: LOCAL_CRATE ; 
4043use  hir:: intravisit as  hir_visit; 
4144use  syntax:: util:: lev_distance:: find_best_match_for_name; 
4245use  syntax:: visit as  ast_visit; 
46+ use  syntax:: ast:: { NodeId ,  CRATE_NODE_ID } ; 
4347
4448/// Information about the registered lints. 
4549/// 
@@ -55,6 +59,7 @@ pub struct LintStore {
5559pre_expansion_passes :  Option < Vec < EarlyLintPassObject > > , 
5660    early_passes :  Option < Vec < EarlyLintPassObject > > , 
5761    late_passes :  Option < Vec < LateLintPassObject > > , 
62+     late_module_passes :  Option < Vec < LateLintPassObject > > , 
5863
5964    /// Lints indexed by name. 
6065by_name :  FxHashMap < String ,  TargetLint > , 
@@ -150,6 +155,7 @@ impl LintStore {
150155            pre_expansion_passes :  Some ( vec ! [ ] ) , 
151156            early_passes :  Some ( vec ! [ ] ) , 
152157            late_passes :  Some ( vec ! [ ] ) , 
158+             late_module_passes :  Some ( vec ! [ ] ) , 
153159            by_name :  Default :: default ( ) , 
154160            future_incompatible :  Default :: default ( ) , 
155161            lint_groups :  Default :: default ( ) , 
@@ -199,9 +205,14 @@ impl LintStore {
199205    pub  fn  register_late_pass ( & mut  self , 
200206                              sess :  Option < & Session > , 
201207                              from_plugin :  bool , 
208+                               per_module :  bool , 
202209                              pass :  LateLintPassObject )  { 
203210        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+         } 
205216    } 
206217
207218    // Helper method for register_early/late_pass 
@@ -508,6 +519,7 @@ pub struct LateContext<'a, 'tcx: 'a> {
508519pub  tcx :  TyCtxt < ' a ,  ' tcx ,  ' tcx > , 
509520
510521    /// Side-tables for the body we are in. 
522+ // FIXME: Make this lazy to avoid running the TypeckTables query? 
511523    pub  tables :  & ' a  ty:: TypeckTables < ' tcx > , 
512524
513525    /// Parameter environment for the item we are in. 
@@ -523,6 +535,9 @@ pub struct LateContext<'a, 'tcx: 'a> {
523535
524536    /// Generic type parameters in scope for the item we are in. 
525537pub  generics :  Option < & ' tcx  hir:: Generics > , 
538+ 
539+     /// We are only looking at one module 
540+ only_module :  bool , 
526541} 
527542
528543/// Context for lint checking of the AST, after expansion, before lowering to 
@@ -801,6 +816,12 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> {
801816    pub  fn  current_lint_root ( & self )  -> ast:: NodeId  { 
802817        self . last_ast_node_with_lint_attrs 
803818    } 
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+     } 
804825} 
805826
806827impl < ' a ,  ' tcx >  LayoutOf  for  LateContext < ' a ,  ' tcx >  { 
@@ -932,9 +953,9 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> {
932953    } 
933954
934955    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+         } 
938959    } 
939960
940961    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>
11991220    } 
12001221} 
12011222
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+     } 
12021241
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 > )  { 
12071282    let  access_levels = & tcx. privacy_access_levels ( LOCAL_CRATE ) ; 
12081283
12091284    let  krate = tcx. hir ( ) . krate ( ) ; 
@@ -1221,6 +1296,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
12211296            } , 
12221297            last_ast_node_with_lint_attrs :  ast:: CRATE_NODE_ID , 
12231298            generics :  None , 
1299+             only_module :  false , 
12241300        } ; 
12251301
12261302        // Visit the whole crate. 
@@ -1240,6 +1316,17 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
12401316    tcx. sess . lint_store . borrow_mut ( ) . late_passes  = passes; 
12411317} 
12421318
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+ 
12431330struct  EarlyLintPassObjects < ' a >  { 
12441331    lints :  & ' a  mut  [ EarlyLintPassObject ] , 
12451332} 
0 commit comments