@@ -17,7 +17,7 @@ use rustc_ast as ast;
1717use rustc_ast_pretty:: pprust;
1818use rustc_data_structures:: {
1919 fx:: FxIndexMap ,
20- sync:: { join , Lock , Lrc } ,
20+ sync:: Lrc ,
2121} ;
2222use rustc_errors:: { Diag , DiagMessage , LintDiagnostic , MultiSpan } ;
2323use rustc_feature:: { Features , GateIssue } ;
@@ -162,9 +162,9 @@ fn lint_expectations(tcx: TyCtxt<'_>, (): ()) -> Vec<(LintExpectationId, LintExp
162162pub fn lints_that_can_emit ( tcx : TyCtxt < ' _ > , ( ) : ( ) ) -> Lrc < ( Vec < String > , Vec < String > ) > {
163163 let mut visitor = LintLevelMinimum :: new ( tcx) ;
164164 visitor. process_opts ( ) ;
165- visitor . lint_level_minimums ( ) ;
165+ tcx . hir ( ) . walk_attributes ( & mut visitor ) ;
166166
167- Lrc :: new ( ( visitor. lints_to_emit . into_inner ( ) , visitor. lints_allowed . into_inner ( ) ) )
167+ Lrc :: new ( ( visitor. lints_to_emit , visitor. lints_allowed ) )
168168}
169169
170170#[ instrument( level = "trace" , skip( tcx) , ret) ]
@@ -474,49 +474,77 @@ impl<'tcx> Visitor<'tcx> for LintLevelsBuilder<'_, QueryMapExpectationsWrapper<'
474474struct LintLevelMinimum < ' tcx > {
475475 tcx : TyCtxt < ' tcx > ,
476476 /// The actual list of detected lints.
477- lints_to_emit : Lock < Vec < String > > ,
478- lints_allowed : Lock < Vec < String > > ,
477+ lints_to_emit : Vec < String > ,
478+ lints_allowed : Vec < String > ,
479479}
480480
481481impl < ' 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 : Lock :: new ( Vec :: with_capacity ( 230 ) ) ,
487- lints_allowed : Lock :: new ( Vec :: with_capacity ( 100 ) ) ,
486+ lints_to_emit : Vec :: with_capacity ( 230 ) ,
487+ lints_allowed : 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 . with_lock ( |lints_allowed| lints_allowed . push ( lint. to_string ( ) ) ) ;
494+ self . lints_allowed . push ( lint. clone ( ) ) ;
495495 } else {
496- self . lints_to_emit . with_lock ( |lints_to_emit| lints_to_emit . push ( lint. to_string ( ) ) ) ;
496+ self . lints_to_emit . push ( lint. to_string ( ) ) ;
497497 }
498498 }
499499 }
500+ }
501+
502+ impl < ' tcx > Visitor < ' tcx > for LintLevelMinimum < ' tcx > {
503+ type NestedFilter = nested_filter:: All ;
504+
505+ fn nested_visit_map ( & mut self ) -> Self :: Map {
506+ self . tcx . hir ( )
507+ }
500508
501- fn lint_level_minimums ( & mut self ) {
502- join (
503- || {
504- self . tcx . sess . psess . lints_that_can_emit . with_lock ( |vec| {
505- for lint_symbol in vec {
506- self . lints_to_emit
507- . with_lock ( |lints_to_emit| lints_to_emit. push ( lint_symbol. to_string ( ) ) ) ;
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 . as_str ( ) . to_string ( ) ,
524+ ) ;
525+ } else {
526+ self . lints_to_emit
527+ . push ( meta_item. path . segments [ 1 ] . ident . name . as_str ( ) . to_string ( ) ) ;
528+ }
508529 }
509- } ) ;
510- } ,
511- || {
512- self . tcx . sess . psess . lints_allowed . with_lock ( |vec| {
513- for lint_symbol in vec {
514- self . lints_allowed
515- . with_lock ( |lints_allowed| lints_allowed. push ( lint_symbol. to_string ( ) ) ) ;
530+ }
531+ // We handle #![allow]s differently, as these remove checking rather than adding.
532+ } else if meta. has_name ( sym:: allow)
533+ && let ast:: AttrStyle :: Inner = attribute. style
534+ {
535+ for meta_list in meta. meta_item_list ( ) . unwrap ( ) {
536+ // If it's a tool lint (e.g. clippy::my_clippy_lint)
537+ if let ast:: NestedMetaItem :: MetaItem ( meta_item) = meta_list {
538+ if meta_item. path . segments . len ( ) == 1 {
539+ self . lints_allowed . push ( meta_list. name_or_empty ( ) . as_str ( ) . to_string ( ) )
540+ } else {
541+ self . lints_allowed
542+ . push ( meta_item. path . segments [ 1 ] . ident . name . as_str ( ) . to_string ( ) ) ;
543+ }
516544 }
517- } ) ;
518- } ,
519- ) ;
545+ }
546+ }
547+ }
520548 }
521549}
522550
0 commit comments