@@ -5,7 +5,8 @@ use rustc_ast_pretty::pprust;
5
5
use rustc_data_structures:: fx:: FxHashMap ;
6
6
use rustc_errors:: { Applicability , Diagnostic , DiagnosticBuilder , DiagnosticMessage , MultiSpan } ;
7
7
use rustc_hir as hir;
8
- use rustc_hir:: { intravisit, HirId } ;
8
+ use rustc_hir:: intravisit:: { self , Visitor } ;
9
+ use rustc_hir:: HirId ;
9
10
use rustc_index:: vec:: IndexVec ;
10
11
use rustc_middle:: hir:: nested_filter;
11
12
use rustc_middle:: lint:: {
@@ -115,6 +116,7 @@ fn lint_expectations(tcx: TyCtxt<'_>, (): ()) -> Vec<(LintExpectationId, LintExp
115
116
specs : ShallowLintLevelMap :: default ( ) ,
116
117
expectations : Vec :: new ( ) ,
117
118
unstable_to_stable_ids : FxHashMap :: default ( ) ,
119
+ empty : FxHashMap :: default ( ) ,
118
120
} ,
119
121
warn_about_weird_lints : false ,
120
122
store,
@@ -130,25 +132,39 @@ fn lint_expectations(tcx: TyCtxt<'_>, (): ()) -> Vec<(LintExpectationId, LintExp
130
132
builder. provider . expectations
131
133
}
132
134
133
- fn shallow_lint_levels_on ( tcx : TyCtxt < ' _ > , hir_id : HirId ) -> ShallowLintLevelMap {
135
+ #[ instrument( level = "trace" , skip( tcx) , ret) ]
136
+ fn shallow_lint_levels_on ( tcx : TyCtxt < ' _ > , owner : hir:: OwnerId ) -> ShallowLintLevelMap {
134
137
let store = unerased_lint_store ( tcx) ;
135
138
136
139
let mut levels = LintLevelsBuilder {
137
140
sess : tcx. sess ,
138
- provider : LintLevelQueryMap { tcx, cur : hir_id, specs : ShallowLintLevelMap :: default ( ) } ,
141
+ provider : LintLevelQueryMap {
142
+ tcx,
143
+ cur : owner. into ( ) ,
144
+ specs : ShallowLintLevelMap :: default ( ) ,
145
+ empty : FxHashMap :: default ( ) ,
146
+ } ,
139
147
warn_about_weird_lints : false ,
140
148
store,
141
149
registered_tools : & tcx. resolutions ( ( ) ) . registered_tools ,
142
150
} ;
143
151
144
- let is_crate = hir:: CRATE_HIR_ID == hir_id;
145
- if is_crate {
146
- levels. add_command_line ( ) ;
147
- }
148
- debug ! ( ?hir_id) ;
149
- levels. add ( tcx. hir ( ) . attrs ( hir_id) , is_crate, Some ( hir_id) ) ;
152
+ match tcx. hir ( ) . expect_owner ( owner) {
153
+ hir:: OwnerNode :: Item ( item) => levels. visit_item ( item) ,
154
+ hir:: OwnerNode :: ForeignItem ( item) => levels. visit_foreign_item ( item) ,
155
+ hir:: OwnerNode :: TraitItem ( item) => levels. visit_trait_item ( item) ,
156
+ hir:: OwnerNode :: ImplItem ( item) => levels. visit_impl_item ( item) ,
157
+ hir:: OwnerNode :: Crate ( mod_) => {
158
+ levels. add_command_line ( ) ;
159
+ levels. add_id ( hir:: CRATE_HIR_ID ) ;
160
+ levels. visit_mod ( mod_, mod_. spans . inner_span , hir:: CRATE_HIR_ID )
161
+ }
162
+ } ;
163
+
164
+ let mut specs = levels. provider . specs ;
165
+ specs. specs . retain ( |( _, v) | !v. is_empty ( ) ) ;
150
166
151
- levels . provider . specs
167
+ specs
152
168
}
153
169
154
170
pub struct TopDown {
@@ -181,14 +197,16 @@ struct LintLevelQueryMap<'tcx> {
181
197
tcx : TyCtxt < ' tcx > ,
182
198
cur : HirId ,
183
199
specs : ShallowLintLevelMap ,
200
+ /// Empty hash map to simplify code.
201
+ empty : FxHashMap < LintId , LevelAndSource > ,
184
202
}
185
203
186
204
impl LintLevelsProvider for LintLevelQueryMap < ' _ > {
187
205
fn current_specs ( & self ) -> & FxHashMap < LintId , LevelAndSource > {
188
- & self . specs . specs
206
+ self . specs . specs . get ( & self . cur . local_id ) . unwrap_or ( & self . empty )
189
207
}
190
208
fn current_specs_mut ( & mut self ) -> & mut FxHashMap < LintId , LevelAndSource > {
191
- & mut self . specs . specs
209
+ self . specs . specs . get_mut_or_insert_default ( self . cur . local_id )
192
210
}
193
211
fn get_lint_level ( & self , lint : & ' static Lint , _: & Session ) -> LevelAndSource {
194
212
self . specs . lint_level_id_at_node ( self . tcx , LintId :: of ( lint) , self . cur )
@@ -201,15 +219,18 @@ struct QueryMapExpectationsWrapper<'tcx> {
201
219
specs : ShallowLintLevelMap ,
202
220
expectations : Vec < ( LintExpectationId , LintExpectation ) > ,
203
221
unstable_to_stable_ids : FxHashMap < LintExpectationId , LintExpectationId > ,
222
+ /// Empty hash map to simplify code.
223
+ empty : FxHashMap < LintId , LevelAndSource > ,
204
224
}
205
225
206
226
impl LintLevelsProvider for QueryMapExpectationsWrapper < ' _ > {
207
227
fn current_specs ( & self ) -> & FxHashMap < LintId , LevelAndSource > {
208
- & self . specs . specs
228
+ self . specs . specs . get ( & self . cur . local_id ) . unwrap_or ( & self . empty )
209
229
}
210
230
fn current_specs_mut ( & mut self ) -> & mut FxHashMap < LintId , LevelAndSource > {
211
- self . specs . specs . clear ( ) ;
212
- & mut self . specs . specs
231
+ let specs = self . specs . specs . get_mut_or_insert_default ( self . cur . local_id ) ;
232
+ specs. clear ( ) ;
233
+ specs
213
234
}
214
235
fn get_lint_level ( & self , lint : & ' static Lint , _: & Session ) -> LevelAndSource {
215
236
self . specs . lint_level_id_at_node ( self . tcx , LintId :: of ( lint) , self . cur )
@@ -229,13 +250,86 @@ impl LintLevelsProvider for QueryMapExpectationsWrapper<'_> {
229
250
}
230
251
}
231
252
253
+ impl < ' tcx > LintLevelsBuilder < ' _ , LintLevelQueryMap < ' tcx > > {
254
+ fn add_id ( & mut self , hir_id : HirId ) {
255
+ self . provider . cur = hir_id;
256
+ self . add ( self . provider . tcx . hir ( ) . attrs ( hir_id) , hir_id == hir:: CRATE_HIR_ID , Some ( hir_id) ) ;
257
+ }
258
+ }
259
+
260
+ impl < ' tcx > Visitor < ' tcx > for LintLevelsBuilder < ' _ , LintLevelQueryMap < ' tcx > > {
261
+ type NestedFilter = nested_filter:: OnlyBodies ;
262
+
263
+ fn nested_visit_map ( & mut self ) -> Self :: Map {
264
+ self . provider . tcx . hir ( )
265
+ }
266
+
267
+ fn visit_param ( & mut self , param : & ' tcx hir:: Param < ' tcx > ) {
268
+ self . add_id ( param. hir_id ) ;
269
+ intravisit:: walk_param ( self , param) ;
270
+ }
271
+
272
+ fn visit_item ( & mut self , it : & ' tcx hir:: Item < ' tcx > ) {
273
+ self . add_id ( it. hir_id ( ) ) ;
274
+ intravisit:: walk_item ( self , it) ;
275
+ }
276
+
277
+ fn visit_foreign_item ( & mut self , it : & ' tcx hir:: ForeignItem < ' tcx > ) {
278
+ self . add_id ( it. hir_id ( ) ) ;
279
+ intravisit:: walk_foreign_item ( self , it) ;
280
+ }
281
+
282
+ fn visit_stmt ( & mut self , e : & ' tcx hir:: Stmt < ' tcx > ) {
283
+ // We will call `add_id` when we walk
284
+ // the `StmtKind`. The outer statement itself doesn't
285
+ // define the lint levels.
286
+ intravisit:: walk_stmt ( self , e) ;
287
+ }
288
+
289
+ fn visit_expr ( & mut self , e : & ' tcx hir:: Expr < ' tcx > ) {
290
+ self . add_id ( e. hir_id ) ;
291
+ intravisit:: walk_expr ( self , e) ;
292
+ }
293
+
294
+ fn visit_field_def ( & mut self , s : & ' tcx hir:: FieldDef < ' tcx > ) {
295
+ self . add_id ( s. hir_id ) ;
296
+ intravisit:: walk_field_def ( self , s) ;
297
+ }
298
+
299
+ fn visit_variant ( & mut self , v : & ' tcx hir:: Variant < ' tcx > ) {
300
+ self . add_id ( v. id ) ;
301
+ intravisit:: walk_variant ( self , v) ;
302
+ }
303
+
304
+ fn visit_local ( & mut self , l : & ' tcx hir:: Local < ' tcx > ) {
305
+ self . add_id ( l. hir_id ) ;
306
+ intravisit:: walk_local ( self , l) ;
307
+ }
308
+
309
+ fn visit_arm ( & mut self , a : & ' tcx hir:: Arm < ' tcx > ) {
310
+ self . add_id ( a. hir_id ) ;
311
+ intravisit:: walk_arm ( self , a) ;
312
+ }
313
+
314
+ fn visit_trait_item ( & mut self , trait_item : & ' tcx hir:: TraitItem < ' tcx > ) {
315
+ self . add_id ( trait_item. hir_id ( ) ) ;
316
+ intravisit:: walk_trait_item ( self , trait_item) ;
317
+ }
318
+
319
+ fn visit_impl_item ( & mut self , impl_item : & ' tcx hir:: ImplItem < ' tcx > ) {
320
+ self . add_id ( impl_item. hir_id ( ) ) ;
321
+ intravisit:: walk_impl_item ( self , impl_item) ;
322
+ }
323
+ }
324
+
232
325
impl < ' tcx > LintLevelsBuilder < ' _ , QueryMapExpectationsWrapper < ' tcx > > {
233
326
fn add_id ( & mut self , hir_id : HirId ) {
327
+ self . provider . cur = hir_id;
234
328
self . add ( self . provider . tcx . hir ( ) . attrs ( hir_id) , hir_id == hir:: CRATE_HIR_ID , Some ( hir_id) ) ;
235
329
}
236
330
}
237
331
238
- impl < ' tcx > intravisit :: Visitor < ' tcx > for LintLevelsBuilder < ' _ , QueryMapExpectationsWrapper < ' tcx > > {
332
+ impl < ' tcx > Visitor < ' tcx > for LintLevelsBuilder < ' _ , QueryMapExpectationsWrapper < ' tcx > > {
239
333
type NestedFilter = nested_filter:: All ;
240
334
241
335
fn nested_visit_map ( & mut self ) -> Self :: Map {
0 commit comments