@@ -15,7 +15,7 @@ use crate::{
1515} ;
1616use rustc_ast as ast;
1717use 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 } } ;
1919use rustc_errors:: { Diag , DiagMessage , LintDiagnostic , MultiSpan } ;
2020use rustc_feature:: { Features , GateIssue } ;
2121use rustc_hir as hir;
@@ -160,11 +160,11 @@ pub fn lints_that_can_emit(tcx: TyCtxt<'_>, (): ()) -> Lrc<(Vec<Symbol>, Vec<Sym
160160 // builder.add_command_line();
161161 // builder.add_id(hir::CRATE_HIR_ID);
162162
163- let mut visitor = LintLevelMinimumVisitor :: new ( tcx) ;
163+ let mut visitor = LintLevelMinimum :: new ( tcx) ;
164164 visitor. process_opts ( ) ;
165- tcx . hir ( ) . walk_attributes ( & mut visitor ) ;
165+ visitor . lint_level_minimums ( tcx ) ;
166166
167- Lrc :: new ( ( visitor. lints_to_emit , visitor. lints_allowed ) )
167+ Lrc :: new ( ( visitor. lints_to_emit . into_inner ( ) , visitor. lints_allowed . into_inner ( ) ) )
168168}
169169
170170#[ instrument( level = "trace" , skip( tcx) , ret) ]
@@ -471,81 +471,97 @@ impl<'tcx> Visitor<'tcx> for LintLevelsBuilder<'_, QueryMapExpectationsWrapper<'
471471///
472472/// E.g., if a crate has a global #![allow(lint)] attribute, but a single item
473473/// uses #[warn(lint)], this visitor will set that lint level as `Warn`
474- struct LintLevelMinimumVisitor < ' tcx > {
474+ struct LintLevelMinimum < ' tcx > {
475475 tcx : TyCtxt < ' tcx > ,
476476 /// 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 > > ,
479479}
480480
481- impl < ' tcx > LintLevelMinimumVisitor < ' tcx > {
481+ impl < ' tcx > LintLevelMinimum < ' tcx > {
482482 pub fn new ( tcx : TyCtxt < ' tcx > ) -> Self {
483483 Self {
484484 tcx,
485485 // 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 ) ) ,
488488 }
489489 }
490490
491491 fn process_opts ( & mut self ) {
492492 for ( lint, level) in & self . tcx . sess . opts . lint_opts {
493493 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) ) } ) ;
495495 } 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) ) } ) ;
497497 }
498498 }
499499 }
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- }
508500
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) } ) ;
544505 }
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+
546515 }
547516}
548517
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+
549565pub struct LintLevelsBuilder < ' s , P > {
550566 sess : & ' s Session ,
551567 features : & ' s Features ,
0 commit comments