27
27
use self :: TargetLint :: * ;
28
28
29
29
use std:: slice;
30
- use rustc_data_structures:: sync:: { RwLock , ReadGuard } ;
30
+ use rustc_data_structures:: sync:: ReadGuard ;
31
31
use lint:: { EarlyLintPassObject , LateLintPassObject } ;
32
32
use lint:: { Level , Lint , LintId , LintPass , LintBuffer } ;
33
33
use lint:: builtin:: BuiltinLintDiagnostics ;
@@ -59,8 +59,8 @@ pub struct LintStore {
59
59
lints : Vec < ( & ' static Lint , bool ) > ,
60
60
61
61
/// 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 > > ,
64
64
early_passes : Option < Vec < EarlyLintPassObject > > ,
65
65
late_passes : Option < Vec < LateLintPassObject > > ,
66
66
@@ -139,6 +139,7 @@ impl LintStore {
139
139
pub fn new ( ) -> LintStore {
140
140
LintStore {
141
141
lints : vec ! [ ] ,
142
+ pre_expansion_passes : Some ( vec ! [ ] ) ,
142
143
early_passes : Some ( vec ! [ ] ) ,
143
144
late_passes : Some ( vec ! [ ] ) ,
144
145
by_name : FxHashMap ( ) ,
@@ -165,6 +166,15 @@ impl LintStore {
165
166
self . early_passes . as_mut ( ) . unwrap ( ) . push ( pass) ;
166
167
}
167
168
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
+
168
178
pub fn register_late_pass ( & mut self ,
169
179
sess : Option < & Session > ,
170
180
from_plugin : bool ,
@@ -332,28 +342,6 @@ impl LintStore {
332
342
}
333
343
}
334
344
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
-
357
345
/// Context for lint checking after type checking.
358
346
pub struct LateContext < ' a , ' tcx : ' a > {
359
347
/// Type context we're checking in.
@@ -405,30 +393,11 @@ macro_rules! run_lints { ($cx:expr, $f:ident, $($args:expr),*) => ({
405
393
$cx. lint_sess_mut( ) . passes = Some ( passes) ;
406
394
} ) }
407
395
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 { }
417
397
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 { }
427
399
428
- fn restore_passes ( store : & mut LintStore , passes : Option < Vec < Self > > ) {
429
- store. late_passes = passes;
430
- }
431
- }
400
+ impl LintPassObject for LateLintPassObject { }
432
401
433
402
434
403
pub trait LintContext < ' tcx > : Sized {
@@ -515,14 +484,21 @@ pub trait LintContext<'tcx>: Sized {
515
484
516
485
517
486
impl < ' 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 > {
520
493
EarlyContext {
521
494
sess,
522
495
krate,
523
- lint_sess : LintSession :: new ( & sess. lint_store ) ,
496
+ lint_sess : LintSession {
497
+ lints : sess. lint_store . borrow ( ) ,
498
+ passes,
499
+ } ,
524
500
builder : LintLevelSets :: builder ( sess) ,
525
- buffered : sess . buffered_lints . borrow_mut ( ) . take ( ) . unwrap ( ) ,
501
+ buffered,
526
502
}
527
503
}
528
504
@@ -1041,9 +1017,14 @@ impl<'a> ast_visit::Visitor<'a> for EarlyContext<'a> {
1041
1017
run_lints ! ( self , check_attribute, attr) ;
1042
1018
}
1043
1019
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) ;
1045
1022
self . check_id ( id) ;
1046
1023
}
1024
+
1025
+ fn visit_mac ( & mut self , mac : & ' ast ast:: Mac ) {
1026
+ run_lints ! ( self , check_mac, mac) ;
1027
+ }
1047
1028
}
1048
1029
1049
1030
@@ -1054,48 +1035,77 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
1054
1035
let access_levels = & tcx. privacy_access_levels ( LOCAL_CRATE ) ;
1055
1036
1056
1037
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
+ } ;
1057
1053
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) ;
1073
1059
1074
- hir_visit:: walk_crate ( cx, krate) ;
1060
+ hir_visit:: walk_crate ( cx, krate) ;
1075
1061
1076
- run_lints ! ( cx, check_crate_post, krate) ;
1077
- } ) ;
1062
+ run_lints ! ( cx, check_crate_post, krate) ;
1063
+ } ) ;
1064
+ cx. lint_sess . passes
1065
+ } ;
1078
1066
1079
1067
// 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 ;
1081
1069
}
1082
1070
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) ;
1085
1089
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) ;
1091
1095
1092
- ast_visit:: walk_crate ( cx, krate) ;
1096
+ ast_visit:: walk_crate ( cx, krate) ;
1093
1097
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
+ } ;
1096
1102
1097
1103
// 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
+ }
1099
1109
1100
1110
// All of the buffered lints should have been emitted at this point.
1101
1111
// 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) {
1107
1117
// unused_macro lint) anymore. So we only run this check
1108
1118
// when we're not in rustdoc mode. (see issue #47639)
1109
1119
if !sess. opts . actually_rustdoc {
1110
- for ( _id, lints) in cx . buffered . map {
1120
+ for ( _id, lints) in buffered. map {
1111
1121
for early_lint in lints {
1112
1122
sess. delay_span_bug ( early_lint. span , "failed to process buffered lint here" ) ;
1113
1123
}
0 commit comments