@@ -15,7 +15,7 @@ use crate::{
15
15
} ;
16
16
use rustc_ast as ast;
17
17
use rustc_ast_pretty:: pprust;
18
- use rustc_data_structures:: { fx:: FxIndexMap , sync:: Lrc } ;
18
+ use rustc_data_structures:: { fx:: FxIndexMap , sync:: { Lrc , par_for_each_in , Lock } } ;
19
19
use rustc_errors:: { Diag , DiagMessage , LintDiagnostic , MultiSpan } ;
20
20
use rustc_feature:: { Features , GateIssue } ;
21
21
use rustc_hir as hir;
@@ -160,11 +160,11 @@ pub fn lints_that_can_emit(tcx: TyCtxt<'_>, (): ()) -> Lrc<(Vec<Symbol>, Vec<Sym
160
160
// builder.add_command_line();
161
161
// builder.add_id(hir::CRATE_HIR_ID);
162
162
163
- let mut visitor = LintLevelMinimumVisitor :: new ( tcx) ;
163
+ let mut visitor = LintLevelMinimum :: new ( tcx) ;
164
164
visitor. process_opts ( ) ;
165
- tcx . hir ( ) . walk_attributes ( & mut visitor ) ;
165
+ visitor . lint_level_minimums ( tcx ) ;
166
166
167
- Lrc :: new ( ( visitor. lints_to_emit , visitor. lints_allowed ) )
167
+ Lrc :: new ( ( visitor. lints_to_emit . into_inner ( ) , visitor. lints_allowed . into_inner ( ) ) )
168
168
}
169
169
170
170
#[ instrument( level = "trace" , skip( tcx) , ret) ]
@@ -471,81 +471,97 @@ impl<'tcx> Visitor<'tcx> for LintLevelsBuilder<'_, QueryMapExpectationsWrapper<'
471
471
///
472
472
/// E.g., if a crate has a global #![allow(lint)] attribute, but a single item
473
473
/// uses #[warn(lint)], this visitor will set that lint level as `Warn`
474
- struct LintLevelMinimumVisitor < ' tcx > {
474
+ struct LintLevelMinimum < ' tcx > {
475
475
tcx : TyCtxt < ' tcx > ,
476
476
/// The actual list of detected lints.
477
- lints_to_emit : Vec < Symbol > ,
478
- lints_allowed : Vec < Symbol > ,
477
+ lints_to_emit : Lock < Vec < Symbol > > ,
478
+ lints_allowed : Lock < Vec < Symbol > > ,
479
479
}
480
480
481
- impl < ' tcx > LintLevelMinimumVisitor < ' tcx > {
481
+ impl < ' tcx > LintLevelMinimum < ' tcx > {
482
482
pub fn new ( tcx : TyCtxt < ' tcx > ) -> Self {
483
483
Self {
484
484
tcx,
485
485
// That magic number is the current number of lints + some more for possible future lints
486
- lints_to_emit : Vec :: with_capacity ( 230 ) ,
487
- lints_allowed : Vec :: with_capacity ( 100 ) ,
486
+ lints_to_emit : Lock :: new ( Vec :: with_capacity ( 230 ) ) ,
487
+ lints_allowed : Lock :: new ( Vec :: with_capacity ( 100 ) ) ,
488
488
}
489
489
}
490
490
491
491
fn process_opts ( & mut self ) {
492
492
for ( lint, level) in & self . tcx . sess . opts . lint_opts {
493
493
if * level == Level :: Allow {
494
- self . lints_allowed . push ( Symbol :: intern ( & lint) ) ;
494
+ self . lints_allowed . with_lock ( |lints_allowed| { lints_allowed . push ( Symbol :: intern ( & lint) ) } ) ;
495
495
} else {
496
- self . lints_to_emit . push ( Symbol :: intern ( & lint) ) ;
496
+ self . lints_to_emit . with_lock ( |lints_to_emit| { lints_to_emit . push ( Symbol :: intern ( & lint) ) } ) ;
497
497
}
498
498
}
499
499
}
500
- }
501
-
502
- impl < ' tcx > Visitor < ' tcx > for LintLevelMinimumVisitor < ' tcx > {
503
- type NestedFilter = nested_filter:: All ;
504
-
505
- fn nested_visit_map ( & mut self ) -> Self :: Map {
506
- self . tcx . hir ( )
507
- }
508
500
509
- fn visit_attribute ( & mut self , attribute : & ' tcx ast:: Attribute ) {
510
- if let Some ( meta) = attribute. meta ( ) {
511
- if [ sym:: warn, sym:: deny, sym:: forbid, sym:: expect]
512
- . iter ( )
513
- . any ( |kind| meta. has_name ( * kind) )
514
- {
515
- // SAFETY: Lint attributes are always a metalist inside a
516
- // metalist (even with just one lint).
517
- for meta_list in meta. meta_item_list ( ) . unwrap ( ) {
518
- // If it's a tool lint (e.g. clippy::my_clippy_lint)
519
- if let ast:: NestedMetaItem :: MetaItem ( meta_item) = meta_list {
520
- if meta_item. path . segments . len ( ) == 1 {
521
- self . lints_to_emit . push (
522
- // SAFETY: Lint attributes can only have literals
523
- meta_list. ident ( ) . unwrap ( ) . name ,
524
- ) ;
525
- } else {
526
- self . lints_to_emit . push ( meta_item. path . segments [ 1 ] . ident . name ) ;
527
- }
528
- }
529
- }
530
- // We handle #![allow]s differently, as these remove checking rather than adding.
531
- } else if meta. has_name ( sym:: allow)
532
- && let ast:: AttrStyle :: Inner = attribute. style
533
- {
534
- for meta_list in meta. meta_item_list ( ) . unwrap ( ) {
535
- // If it's a tool lint (e.g. clippy::my_clippy_lint)
536
- if let ast:: NestedMetaItem :: MetaItem ( meta_item) = meta_list {
537
- if meta_item. path . segments . len ( ) == 1 {
538
- self . lints_allowed . push ( meta_list. name_or_empty ( ) )
539
- } else {
540
- self . lints_allowed . push ( meta_item. path . segments [ 1 ] . ident . name ) ;
541
- }
542
- }
543
- }
501
+ fn lint_level_minimums ( & mut self , tcx : TyCtxt < ' tcx > ) {
502
+ tcx. sess . psess . lints_that_can_emit . with_lock ( |vec| {
503
+ par_for_each_in ( vec, |lint_symbol| {
504
+ self . lints_to_emit . with_lock ( |lints_to_emit| { lints_to_emit. push ( * lint_symbol) } ) ;
544
505
}
545
- }
506
+ ) ;
507
+ } ) ;
508
+ tcx. sess . psess . lints_allowed . with_lock ( |vec| {
509
+ par_for_each_in ( vec, |lint_symbol| {
510
+ self . lints_allowed . with_lock ( |lints_allowed| { lints_allowed. push ( * lint_symbol) } ) ;
511
+ }
512
+ ) ;
513
+ } ) ;
514
+
546
515
}
547
516
}
548
517
518
+ // impl<'tcx> Visitor<'tcx> for LintLevelMinimum<'tcx> {
519
+ // type NestedFilter = nested_filter::All;
520
+
521
+ // fn nested_visit_map(&mut self) -> Self::Map {
522
+ // self.tcx.hir()
523
+ // }
524
+
525
+ // fn visit_attribute(&mut self, attribute: &'tcx ast::Attribute) {
526
+ // if let Some(meta) = attribute.meta() {
527
+ // if [sym::warn, sym::deny, sym::forbid, sym::expect]
528
+ // .iter()
529
+ // .any(|kind| meta.has_name(*kind))
530
+ // {
531
+ // // SAFETY: Lint attributes are always a metalist inside a
532
+ // // metalist (even with just one lint).
533
+ // for meta_list in meta.meta_item_list().unwrap() {
534
+ // // If it's a tool lint (e.g. clippy::my_clippy_lint)
535
+ // if let ast::NestedMetaItem::MetaItem(meta_item) = meta_list {
536
+ // if meta_item.path.segments.len() == 1 {
537
+ // self.lints_to_emit.push(
538
+ // // SAFETY: Lint attributes can only have literals
539
+ // meta_list.ident().unwrap().name,
540
+ // );
541
+ // } else {
542
+ // self.lints_to_emit.push(meta_item.path.segments[1].ident.name);
543
+ // }
544
+ // }
545
+ // }
546
+ // // We handle #![allow]s differently, as these remove checking rather than adding.
547
+ // } else if meta.has_name(sym::allow)
548
+ // && let ast::AttrStyle::Inner = attribute.style
549
+ // {
550
+ // for meta_list in meta.meta_item_list().unwrap() {
551
+ // // If it's a tool lint (e.g. clippy::my_clippy_lint)
552
+ // if let ast::NestedMetaItem::MetaItem(meta_item) = meta_list {
553
+ // if meta_item.path.segments.len() == 1 {
554
+ // self.lints_allowed.push(meta_list.name_or_empty())
555
+ // } else {
556
+ // self.lints_allowed.push(meta_item.path.segments[1].ident.name);
557
+ // }
558
+ // }
559
+ // }
560
+ // }
561
+ // }
562
+ // }
563
+ // }
564
+
549
565
pub struct LintLevelsBuilder < ' s , P > {
550
566
sess : & ' s Session ,
551
567
features : & ' s Features ,
0 commit comments