2727use self :: TargetLint :: * ;
2828
2929use std:: slice;
30- use rustc_data_structures:: sync:: { RwLock , ReadGuard } ;
30+ use rustc_data_structures:: sync:: ReadGuard ;
3131use lint:: { EarlyLintPassObject , LateLintPassObject } ;
3232use lint:: { Level , Lint , LintId , LintPass , LintBuffer } ;
3333use lint:: builtin:: BuiltinLintDiagnostics ;
@@ -59,8 +59,8 @@ pub struct LintStore {
5959 lints : Vec < ( & ' static Lint , bool ) > ,
6060
6161 /// Trait objects for each lint pass.
62- /// This is only `None` while performing a lint pass. See the definition
63- /// of `LintSession::new`.
62+ /// This is only `None` while performing a lint pass.
63+ pre_expansion_passes : Option < Vec < EarlyLintPassObject > > ,
6464 early_passes : Option < Vec < EarlyLintPassObject > > ,
6565 late_passes : Option < Vec < LateLintPassObject > > ,
6666
@@ -139,6 +139,7 @@ impl LintStore {
139139 pub fn new ( ) -> LintStore {
140140 LintStore {
141141 lints : vec ! [ ] ,
142+ pre_expansion_passes : Some ( vec ! [ ] ) ,
142143 early_passes : Some ( vec ! [ ] ) ,
143144 late_passes : Some ( vec ! [ ] ) ,
144145 by_name : FxHashMap ( ) ,
@@ -165,6 +166,15 @@ impl LintStore {
165166 self . early_passes . as_mut ( ) . unwrap ( ) . push ( pass) ;
166167 }
167168
169+ pub fn register_pre_expansion_pass (
170+ & mut self ,
171+ sess : Option < & Session > ,
172+ pass : EarlyLintPassObject ,
173+ ) {
174+ self . push_pass ( sess, false , & pass) ;
175+ self . pre_expansion_passes . as_mut ( ) . unwrap ( ) . push ( pass) ;
176+ }
177+
168178 pub fn register_late_pass ( & mut self ,
169179 sess : Option < & Session > ,
170180 from_plugin : bool ,
@@ -332,28 +342,6 @@ impl LintStore {
332342 }
333343}
334344
335- impl < ' a , PassObject : LintPassObject > LintSession < ' a , PassObject > {
336- /// Creates a new `LintSession`, by moving out the `LintStore`'s initial
337- /// lint levels and pass objects. These can be restored using the `restore`
338- /// method.
339- fn new ( store : & ' a RwLock < LintStore > ) -> LintSession < ' a , PassObject > {
340- let mut s = store. borrow_mut ( ) ;
341- let passes = PassObject :: take_passes ( & mut * s) ;
342- drop ( s) ;
343- LintSession {
344- lints : store. borrow ( ) ,
345- passes,
346- }
347- }
348-
349- /// Restores the levels back to the original lint store.
350- fn restore ( self , store : & RwLock < LintStore > ) {
351- drop ( self . lints ) ;
352- let mut s = store. borrow_mut ( ) ;
353- PassObject :: restore_passes ( & mut * s, self . passes ) ;
354- }
355- }
356-
357345/// Context for lint checking after type checking.
358346pub struct LateContext < ' a , ' tcx : ' a > {
359347 /// Type context we're checking in.
@@ -405,30 +393,11 @@ macro_rules! run_lints { ($cx:expr, $f:ident, $($args:expr),*) => ({
405393 $cx. lint_sess_mut( ) . passes = Some ( passes) ;
406394} ) }
407395
408- pub trait LintPassObject : Sized {
409- fn take_passes ( store : & mut LintStore ) -> Option < Vec < Self > > ;
410- fn restore_passes ( store : & mut LintStore , passes : Option < Vec < Self > > ) ;
411- }
412-
413- impl LintPassObject for EarlyLintPassObject {
414- fn take_passes ( store : & mut LintStore ) -> Option < Vec < Self > > {
415- store. early_passes . take ( )
416- }
396+ pub trait LintPassObject : Sized { }
417397
418- fn restore_passes ( store : & mut LintStore , passes : Option < Vec < Self > > ) {
419- store. early_passes = passes;
420- }
421- }
422-
423- impl LintPassObject for LateLintPassObject {
424- fn take_passes ( store : & mut LintStore ) -> Option < Vec < Self > > {
425- store. late_passes . take ( )
426- }
398+ impl LintPassObject for EarlyLintPassObject { }
427399
428- fn restore_passes ( store : & mut LintStore , passes : Option < Vec < Self > > ) {
429- store. late_passes = passes;
430- }
431- }
400+ impl LintPassObject for LateLintPassObject { }
432401
433402
434403pub trait LintContext < ' tcx > : Sized {
@@ -515,14 +484,21 @@ pub trait LintContext<'tcx>: Sized {
515484
516485
517486impl < ' a > EarlyContext < ' a > {
518- fn new ( sess : & ' a Session ,
519- krate : & ' a ast:: Crate ) -> EarlyContext < ' a > {
487+ fn new (
488+ sess : & ' a Session ,
489+ krate : & ' a ast:: Crate ,
490+ passes : Option < Vec < EarlyLintPassObject > > ,
491+ buffered : LintBuffer ,
492+ ) -> EarlyContext < ' a > {
520493 EarlyContext {
521494 sess,
522495 krate,
523- lint_sess : LintSession :: new ( & sess. lint_store ) ,
496+ lint_sess : LintSession {
497+ lints : sess. lint_store . borrow ( ) ,
498+ passes,
499+ } ,
524500 builder : LintLevelSets :: builder ( sess) ,
525- buffered : sess . buffered_lints . borrow_mut ( ) . take ( ) . unwrap ( ) ,
501+ buffered,
526502 }
527503 }
528504
@@ -1041,9 +1017,14 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> {
10411017 run_lints ! ( self , check_attribute, attr) ;
10421018 }
10431019
1044- fn visit_mac_def ( & mut self , _mac : & ' a ast:: MacroDef , id : ast:: NodeId ) {
1020+ fn visit_mac_def ( & mut self , mac : & ' a ast:: MacroDef , id : ast:: NodeId ) {
1021+ run_lints ! ( self , check_mac_def, mac, id) ;
10451022 self . check_id ( id) ;
10461023 }
1024+
1025+ fn visit_mac ( & mut self , mac : & ' ast ast:: Mac ) {
1026+ run_lints ! ( self , check_mac, mac) ;
1027+ }
10471028}
10481029
10491030
@@ -1054,48 +1035,77 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
10541035 let access_levels = & tcx. privacy_access_levels ( LOCAL_CRATE ) ;
10551036
10561037 let krate = tcx. hir . krate ( ) ;
1038+ let passes = tcx. sess . lint_store . borrow_mut ( ) . late_passes . take ( ) ;
1039+
1040+ let passes = {
1041+ let mut cx = LateContext {
1042+ tcx,
1043+ tables : & ty:: TypeckTables :: empty ( None ) ,
1044+ param_env : ty:: ParamEnv :: empty ( ) ,
1045+ access_levels,
1046+ lint_sess : LintSession {
1047+ passes,
1048+ lints : tcx. sess . lint_store . borrow ( ) ,
1049+ } ,
1050+ last_ast_node_with_lint_attrs : ast:: CRATE_NODE_ID ,
1051+ generics : None ,
1052+ } ;
10571053
1058- let mut cx = LateContext {
1059- tcx,
1060- tables : & ty:: TypeckTables :: empty ( None ) ,
1061- param_env : ty:: ParamEnv :: empty ( ) ,
1062- access_levels,
1063- lint_sess : LintSession :: new ( & tcx. sess . lint_store ) ,
1064- last_ast_node_with_lint_attrs : ast:: CRATE_NODE_ID ,
1065- generics : None ,
1066- } ;
1067-
1068- // Visit the whole crate.
1069- cx. with_lint_attrs ( ast:: CRATE_NODE_ID , & krate. attrs , |cx| {
1070- // since the root module isn't visited as an item (because it isn't an
1071- // item), warn for it here.
1072- run_lints ! ( cx, check_crate, krate) ;
1054+ // Visit the whole crate.
1055+ cx. with_lint_attrs ( ast:: CRATE_NODE_ID , & krate. attrs , |cx| {
1056+ // since the root module isn't visited as an item (because it isn't an
1057+ // item), warn for it here.
1058+ run_lints ! ( cx, check_crate, krate) ;
10731059
1074- hir_visit:: walk_crate ( cx, krate) ;
1060+ hir_visit:: walk_crate ( cx, krate) ;
10751061
1076- run_lints ! ( cx, check_crate_post, krate) ;
1077- } ) ;
1062+ run_lints ! ( cx, check_crate_post, krate) ;
1063+ } ) ;
1064+ cx. lint_sess . passes
1065+ } ;
10781066
10791067 // Put the lint store levels and passes back in the session.
1080- cx . lint_sess . restore ( & tcx. sess . lint_store ) ;
1068+ tcx. sess . lint_store . borrow_mut ( ) . late_passes = passes ;
10811069}
10821070
1083- pub fn check_ast_crate ( sess : & Session , krate : & ast:: Crate ) {
1084- let mut cx = EarlyContext :: new ( sess, krate) ;
1071+ pub fn check_ast_crate (
1072+ sess : & Session ,
1073+ krate : & ast:: Crate ,
1074+ pre_expansion : bool ,
1075+ ) {
1076+ let ( passes, buffered) = if pre_expansion {
1077+ (
1078+ sess. lint_store . borrow_mut ( ) . pre_expansion_passes . take ( ) ,
1079+ LintBuffer :: new ( ) ,
1080+ )
1081+ } else {
1082+ (
1083+ sess. lint_store . borrow_mut ( ) . early_passes . take ( ) ,
1084+ sess. buffered_lints . borrow_mut ( ) . take ( ) . unwrap ( ) ,
1085+ )
1086+ } ;
1087+ let ( passes, buffered) = {
1088+ let mut cx = EarlyContext :: new ( sess, krate, passes, buffered) ;
10851089
1086- // Visit the whole crate.
1087- cx. with_lint_attrs ( ast:: CRATE_NODE_ID , & krate. attrs , |cx| {
1088- // since the root module isn't visited as an item (because it isn't an
1089- // item), warn for it here.
1090- run_lints ! ( cx, check_crate, krate) ;
1090+ // Visit the whole crate.
1091+ cx. with_lint_attrs ( ast:: CRATE_NODE_ID , & krate. attrs , |cx| {
1092+ // since the root module isn't visited as an item (because it isn't an
1093+ // item), warn for it here.
1094+ run_lints ! ( cx, check_crate, krate) ;
10911095
1092- ast_visit:: walk_crate ( cx, krate) ;
1096+ ast_visit:: walk_crate ( cx, krate) ;
10931097
1094- run_lints ! ( cx, check_crate_post, krate) ;
1095- } ) ;
1098+ run_lints ! ( cx, check_crate_post, krate) ;
1099+ } ) ;
1100+ ( cx. lint_sess . passes , cx. buffered )
1101+ } ;
10961102
10971103 // Put the lint store levels and passes back in the session.
1098- cx. lint_sess . restore ( & sess. lint_store ) ;
1104+ if pre_expansion {
1105+ sess. lint_store . borrow_mut ( ) . pre_expansion_passes = passes;
1106+ } else {
1107+ sess. lint_store . borrow_mut ( ) . early_passes = passes;
1108+ }
10991109
11001110 // All of the buffered lints should have been emitted at this point.
11011111 // If not, that means that we somehow buffered a lint for a node id
@@ -1107,7 +1117,7 @@ pub fn check_ast_crate(sess: &Session, krate: &ast::Crate) {
11071117 // unused_macro lint) anymore. So we only run this check
11081118 // when we're not in rustdoc mode. (see issue #47639)
11091119 if !sess. opts . actually_rustdoc {
1110- for ( _id, lints) in cx . buffered . map {
1120+ for ( _id, lints) in buffered. map {
11111121 for early_lint in lints {
11121122 sess. delay_span_bug ( early_lint. span , "failed to process buffered lint here" ) ;
11131123 }
0 commit comments