@@ -6,10 +6,11 @@ use rustc_data_structures::fx::FxHashMap;
66use rustc_errors:: { Applicability , Diagnostic , LintDiagnosticBuilder , MultiSpan } ;
77use rustc_hir as hir;
88use rustc_hir:: { intravisit, HirId } ;
9+ use rustc_index:: vec:: IndexVec ;
910use rustc_middle:: hir:: nested_filter;
1011use rustc_middle:: lint:: {
11- struct_lint_level, LevelAndSource , LintExpectation , LintLevelQueryMap , LintLevelSets ,
12- LintLevelSource , LintSet , LintStackIndex , COMMAND_LINE ,
12+ reveal_actual_level , struct_lint_level, LevelAndSource , LintExpectation , LintLevelSource ,
13+ ShallowLintLevelMap ,
1314} ;
1415use rustc_middle:: ty:: query:: Providers ;
1516use rustc_middle:: ty:: { RegisteredTools , TyCtxt } ;
@@ -27,13 +28,80 @@ use crate::errors::{
2728 UnknownToolInScopedLint ,
2829} ;
2930
31+ #[ derive( Debug ) ]
32+ struct LintLevelSets {
33+ list : IndexVec < LintStackIndex , LintSet > ,
34+ }
35+
36+ rustc_index:: newtype_index! {
37+ struct LintStackIndex {
38+ ENCODABLE = custom, // we don't need encoding
39+ const COMMAND_LINE = 0 ,
40+ }
41+ }
42+
43+ #[ derive( Debug ) ]
44+ struct LintSet {
45+ // -A,-W,-D flags, a `Symbol` for the flag itself and `Level` for which
46+ // flag.
47+ specs : FxHashMap < LintId , LevelAndSource > ,
48+
49+ parent : LintStackIndex ,
50+ }
51+
52+ impl LintLevelSets {
53+ fn new ( ) -> Self {
54+ LintLevelSets { list : IndexVec :: new ( ) }
55+ }
56+
57+ fn get_lint_level (
58+ & self ,
59+ lint : & ' static Lint ,
60+ idx : LintStackIndex ,
61+ aux : Option < & FxHashMap < LintId , LevelAndSource > > ,
62+ sess : & Session ,
63+ ) -> LevelAndSource {
64+ let lint = LintId :: of ( lint) ;
65+ let ( level, mut src) = self . raw_lint_id_level ( lint, idx, aux) ;
66+ let level = reveal_actual_level ( level, & mut src, sess, lint, |id| {
67+ self . raw_lint_id_level ( id, idx, aux)
68+ } ) ;
69+ ( level, src)
70+ }
71+
72+ fn raw_lint_id_level (
73+ & self ,
74+ id : LintId ,
75+ mut idx : LintStackIndex ,
76+ aux : Option < & FxHashMap < LintId , LevelAndSource > > ,
77+ ) -> ( Option < Level > , LintLevelSource ) {
78+ if let Some ( specs) = aux {
79+ if let Some ( & ( level, src) ) = specs. get ( & id) {
80+ return ( Some ( level) , src) ;
81+ }
82+ }
83+ loop {
84+ let LintSet { ref specs, parent } = self . list [ idx] ;
85+ if let Some ( & ( level, src) ) = specs. get ( & id) {
86+ return ( Some ( level) , src) ;
87+ }
88+ if idx == COMMAND_LINE {
89+ return ( None , LintLevelSource :: Default ) ;
90+ }
91+ idx = parent;
92+ }
93+ }
94+ }
95+
3096fn lint_expectations ( tcx : TyCtxt < ' _ > , ( ) : ( ) ) -> Vec < ( LintExpectationId , LintExpectation ) > {
3197 let store = unerased_lint_store ( tcx) ;
3298
3399 let mut builder = LintLevelsBuilder {
34100 sess : tcx. sess ,
35101 provider : QueryMapExpectationsWrapper {
36- map : LintLevelQueryMap { tcx, cur : hir:: CRATE_HIR_ID , specs : FxHashMap :: default ( ) } ,
102+ tcx,
103+ cur : hir:: CRATE_HIR_ID ,
104+ specs : ShallowLintLevelMap :: default ( ) ,
37105 expectations : Vec :: new ( ) ,
38106 unstable_to_stable_ids : FxHashMap :: default ( ) ,
39107 } ,
@@ -51,12 +119,12 @@ fn lint_expectations(tcx: TyCtxt<'_>, (): ()) -> Vec<(LintExpectationId, LintExp
51119 builder. provider . expectations
52120}
53121
54- fn lint_levels_on ( tcx : TyCtxt < ' _ > , hir_id : HirId ) -> FxHashMap < LintId , LevelAndSource > {
122+ fn shallow_lint_levels_on ( tcx : TyCtxt < ' _ > , hir_id : HirId ) -> ShallowLintLevelMap {
55123 let store = unerased_lint_store ( tcx) ;
56124
57125 let mut levels = LintLevelsBuilder {
58126 sess : tcx. sess ,
59- provider : LintLevelQueryMap { tcx, cur : hir_id, specs : FxHashMap :: default ( ) } ,
127+ provider : LintLevelQueryMap { tcx, cur : hir_id, specs : ShallowLintLevelMap :: default ( ) } ,
60128 warn_about_weird_lints : false ,
61129 store,
62130 registered_tools : & tcx. resolutions ( ( ) ) . registered_tools ,
@@ -77,12 +145,6 @@ pub struct TopDown {
77145 cur : LintStackIndex ,
78146}
79147
80- pub struct QueryMapExpectationsWrapper < ' tcx > {
81- map : LintLevelQueryMap < ' tcx > ,
82- expectations : Vec < ( LintExpectationId , LintExpectation ) > ,
83- unstable_to_stable_ids : FxHashMap < LintExpectationId , LintExpectationId > ,
84- }
85-
86148pub trait LintLevelsProvider {
87149 fn current_specs ( & self ) -> & FxHashMap < LintId , LevelAndSource > ;
88150 fn current_specs_mut ( & mut self ) -> & mut FxHashMap < LintId , LevelAndSource > ;
@@ -104,28 +166,42 @@ impl LintLevelsProvider for TopDown {
104166 }
105167}
106168
169+ struct LintLevelQueryMap < ' tcx > {
170+ tcx : TyCtxt < ' tcx > ,
171+ cur : HirId ,
172+ specs : ShallowLintLevelMap ,
173+ }
174+
107175impl LintLevelsProvider for LintLevelQueryMap < ' _ > {
108176 fn current_specs ( & self ) -> & FxHashMap < LintId , LevelAndSource > {
109- & self . specs
177+ & self . specs . specs
110178 }
111179 fn current_specs_mut ( & mut self ) -> & mut FxHashMap < LintId , LevelAndSource > {
112- & mut self . specs
180+ & mut self . specs . specs
113181 }
114182 fn get_lint_level ( & self , lint : & ' static Lint , _: & Session ) -> LevelAndSource {
115- self . lint_level ( lint)
183+ self . specs . lint_level_id_at_node ( self . tcx , LintId :: of ( lint) , self . cur )
116184 }
117185}
118186
187+ struct QueryMapExpectationsWrapper < ' tcx > {
188+ tcx : TyCtxt < ' tcx > ,
189+ cur : HirId ,
190+ specs : ShallowLintLevelMap ,
191+ expectations : Vec < ( LintExpectationId , LintExpectation ) > ,
192+ unstable_to_stable_ids : FxHashMap < LintExpectationId , LintExpectationId > ,
193+ }
194+
119195impl LintLevelsProvider for QueryMapExpectationsWrapper < ' _ > {
120196 fn current_specs ( & self ) -> & FxHashMap < LintId , LevelAndSource > {
121- & self . map . specs
197+ & self . specs . specs
122198 }
123199 fn current_specs_mut ( & mut self ) -> & mut FxHashMap < LintId , LevelAndSource > {
124- self . map . specs . clear ( ) ;
125- & mut self . map . specs
200+ self . specs . specs . clear ( ) ;
201+ & mut self . specs . specs
126202 }
127203 fn get_lint_level ( & self , lint : & ' static Lint , _: & Session ) -> LevelAndSource {
128- self . map . lint_level ( lint)
204+ self . specs . lint_level_id_at_node ( self . tcx , LintId :: of ( lint) , self . cur )
129205 }
130206 fn push_expectation ( & mut self , id : LintExpectationId , expectation : LintExpectation ) {
131207 let LintExpectationId :: Stable { attr_id : Some ( attr_id) , hir_id, attr_index, .. } = id else { bug ! ( "unstable expectation id should already be mapped" ) } ;
@@ -144,19 +220,15 @@ impl LintLevelsProvider for QueryMapExpectationsWrapper<'_> {
144220
145221impl < ' tcx > LintLevelsBuilder < ' _ , QueryMapExpectationsWrapper < ' tcx > > {
146222 fn add_id ( & mut self , hir_id : HirId ) {
147- self . add (
148- self . provider . map . tcx . hir ( ) . attrs ( hir_id) ,
149- hir_id == hir:: CRATE_HIR_ID ,
150- Some ( hir_id) ,
151- ) ;
223+ self . add ( self . provider . tcx . hir ( ) . attrs ( hir_id) , hir_id == hir:: CRATE_HIR_ID , Some ( hir_id) ) ;
152224 }
153225}
154226
155227impl < ' tcx > intravisit:: Visitor < ' tcx > for LintLevelsBuilder < ' _ , QueryMapExpectationsWrapper < ' tcx > > {
156228 type NestedFilter = nested_filter:: All ;
157229
158230 fn nested_visit_map ( & mut self ) -> Self :: Map {
159- self . provider . map . tcx . hir ( )
231+ self . provider . tcx . hir ( )
160232 }
161233
162234 fn visit_param ( & mut self , param : & ' tcx hir:: Param < ' tcx > ) {
@@ -225,13 +297,12 @@ pub struct LintLevelsBuilder<'s, P> {
225297 registered_tools : & ' s RegisteredTools ,
226298}
227299
228- pub struct BuilderPush {
300+ pub ( crate ) struct BuilderPush {
229301 prev : LintStackIndex ,
230- pub changed : bool ,
231302}
232303
233304impl < ' s > LintLevelsBuilder < ' s , TopDown > {
234- pub fn new (
305+ pub ( crate ) fn new (
235306 sess : & ' s Session ,
236307 warn_about_weird_lints : bool ,
237308 store : & ' s LintStore ,
@@ -289,11 +360,11 @@ impl<'s> LintLevelsBuilder<'s, TopDown> {
289360 self . provider . cur = prev;
290361 }
291362
292- BuilderPush { prev, changed : prev != self . provider . cur }
363+ BuilderPush { prev }
293364 }
294365
295366 /// Called after `push` when the scope of a set of attributes are exited.
296- pub fn pop ( & mut self , push : BuilderPush ) {
367+ pub ( crate ) fn pop ( & mut self , push : BuilderPush ) {
297368 self . provider . cur = push. prev ;
298369 }
299370}
@@ -855,7 +926,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
855926
856927 /// Used to emit a lint-related diagnostic based on the current state of
857928 /// this lint context.
858- pub fn struct_lint (
929+ pub ( crate ) fn struct_lint (
859930 & self ,
860931 lint : & ' static Lint ,
861932 span : Option < MultiSpan > ,
@@ -866,6 +937,6 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
866937 }
867938}
868939
869- pub fn provide ( providers : & mut Providers ) {
870- * providers = Providers { lint_levels_on , lint_expectations, ..* providers } ;
940+ pub ( crate ) fn provide ( providers : & mut Providers ) {
941+ * providers = Providers { shallow_lint_levels_on , lint_expectations, ..* providers } ;
871942}
0 commit comments