@@ -24,9 +24,10 @@ pub use self::LintSource::*;
2424use  rustc_data_structures:: sync:: { self ,  Lrc } ; 
2525
2626use  errors:: { DiagnosticBuilder ,  DiagnosticId } ; 
27- use  hir:: def_id:: { CrateNum ,  LOCAL_CRATE } ; 
27+ use  hir:: def_id:: { CrateNum ,  DefId ,   LOCAL_CRATE } ; 
2828use  hir:: intravisit; 
2929use  hir; 
30+ use  hir:: CRATE_HIR_ID ; 
3031use  lint:: builtin:: BuiltinLintDiagnostics ; 
3132use  lint:: builtin:: parser:: { QUESTION_MARK_MACRO_SEP ,  ILL_FORMED_ATTRIBUTE_INPUT } ; 
3233use  session:: { Session ,  DiagnosticMessageId } ; 
@@ -540,7 +541,7 @@ impl Level {
540541} 
541542
542543/// How a lint level was set. 
543- #[ derive( Clone ,  Copy ,  PartialEq ,  Eq ) ]  
544+ #[ derive( Clone ,  Copy ,  PartialEq ,  Eq ,   Debug ) ]  
544545pub  enum  LintSource  { 
545546    /// Lint is at the default level as declared 
546547/// in rustc or a plugin. 
@@ -722,11 +723,32 @@ fn lint_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cnum: CrateNum)
722723    } ; 
723724    let  krate = tcx. hir ( ) . krate ( ) ; 
724725
725-     builder. with_lint_attrs ( ast:: CRATE_NODE_ID ,  & krate. attrs ,  |builder| { 
726-         intravisit:: walk_crate ( builder,  krate) ; 
727-     } ) ; 
726+     let  push = builder. levels . push ( & krate. attrs ) ; 
727+     builder. levels . register_id ( CRATE_HIR_ID ) ; 
728+     intravisit:: walk_crate ( & mut  builder,  krate) ; 
729+     builder. levels . pop ( push) ; 
728730
729-     Lrc :: new ( builder. levels . build_map ( ) ) 
731+     let  r = Lrc :: new ( builder. levels . build_map ( ) ) ; 
732+     if  tcx. sess . verbose ( )  { 
733+         eprintln ! ( "lint level map: {:#?}" ,  r) ; 
734+     } 
735+     r
736+ } 
737+ 
738+ fn  lint_level_root_for_def_id ( tcx :  TyCtxt < ' a ,  ' tcx ,  ' tcx > ,  def_id :  DefId )  -> hir:: HirId  { 
739+     let  mut  id = tcx. hir ( ) . as_local_hir_id ( def_id) . unwrap ( ) ; 
740+     let  sets = tcx. lint_levels ( LOCAL_CRATE ) ; 
741+     loop  { 
742+         if  sets. lint_level_set ( id) . is_some ( )  { 
743+             return  id
744+         } 
745+         let  node_id =  tcx. hir ( ) . hir_to_node_id ( id) ; 
746+         let  next = tcx. hir ( ) . node_to_hir_id ( tcx. hir ( ) . get_parent_node ( node_id) ) ; 
747+         if  next == id { 
748+             bug ! ( "lint traversal reached the root of the crate" ) ; 
749+         } 
750+         id = next; 
751+     } 
730752} 
731753
732754struct  LintLevelMapBuilder < ' a ,  ' tcx :  ' a >  { 
@@ -742,7 +764,9 @@ impl<'a, 'tcx> LintLevelMapBuilder<'a, 'tcx> {
742764        where  F :  FnOnce ( & mut  Self ) 
743765    { 
744766        let  push = self . levels . push ( attrs) ; 
745-         self . levels . register_id ( self . tcx . hir ( ) . definitions ( ) . node_to_hir_id ( id) ) ; 
767+         if  push. changed  { 
768+             self . levels . register_id ( self . tcx . hir ( ) . definitions ( ) . node_to_hir_id ( id) ) ; 
769+         } 
746770        f ( self ) ; 
747771        self . levels . pop ( push) ; 
748772    } 
@@ -807,6 +831,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'a, 'tcx> {
807831
808832pub  fn  provide ( providers :  & mut  Providers < ' _ > )  { 
809833    providers. lint_levels  = lint_levels; 
834+     providers. lint_level_root_for_def_id  = lint_level_root_for_def_id; 
810835} 
811836
812837/// Returns whether `span` originates in a foreign crate's external macro. 
0 commit comments