@@ -24,9 +24,10 @@ pub use self::LintSource::*;
24
24
use rustc_data_structures:: sync:: { self , Lrc } ;
25
25
26
26
use errors:: { DiagnosticBuilder , DiagnosticId } ;
27
- use hir:: def_id:: { CrateNum , LOCAL_CRATE } ;
27
+ use hir:: def_id:: { CrateNum , DefId , LOCAL_CRATE } ;
28
28
use hir:: intravisit;
29
29
use hir;
30
+ use hir:: CRATE_HIR_ID ;
30
31
use lint:: builtin:: BuiltinLintDiagnostics ;
31
32
use lint:: builtin:: parser:: { QUESTION_MARK_MACRO_SEP , ILL_FORMED_ATTRIBUTE_INPUT } ;
32
33
use session:: { Session , DiagnosticMessageId } ;
@@ -540,7 +541,7 @@ impl Level {
540
541
}
541
542
542
543
/// How a lint level was set.
543
- #[ derive( Clone , Copy , PartialEq , Eq ) ]
544
+ #[ derive( Clone , Copy , PartialEq , Eq , Debug ) ]
544
545
pub enum LintSource {
545
546
/// Lint is at the default level as declared
546
547
/// in rustc or a plugin.
@@ -722,11 +723,32 @@ fn lint_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cnum: CrateNum)
722
723
} ;
723
724
let krate = tcx. hir ( ) . krate ( ) ;
724
725
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) ;
728
730
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
+ }
730
752
}
731
753
732
754
struct LintLevelMapBuilder < ' a , ' tcx : ' a > {
@@ -742,7 +764,9 @@ impl<'a, 'tcx> LintLevelMapBuilder<'a, 'tcx> {
742
764
where F : FnOnce ( & mut Self )
743
765
{
744
766
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
+ }
746
770
f ( self ) ;
747
771
self . levels . pop ( push) ;
748
772
}
@@ -807,6 +831,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'a, 'tcx> {
807
831
808
832
pub fn provide ( providers : & mut Providers < ' _ > ) {
809
833
providers. lint_levels = lint_levels;
834
+ providers. lint_level_root_for_def_id = lint_level_root_for_def_id;
810
835
}
811
836
812
837
/// Returns whether `span` originates in a foreign crate's external macro.
0 commit comments