Skip to content

Commit d08669c

Browse files
committed
Compute by owner instead of HirId.
1 parent 26e5fe9 commit d08669c

File tree

5 files changed

+147
-25
lines changed

5 files changed

+147
-25
lines changed

compiler/rustc_data_structures/src/vec_map.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,20 @@ where
5353
self.0.iter_mut().find(|(key, _)| k == key.borrow()).map(|elem| &mut elem.1)
5454
}
5555

56+
/// Gets a mutable reference to the value in the entry, or insert a new one.
57+
pub fn get_mut_or_insert_default(&mut self, k: K) -> &mut V
58+
where
59+
K: Eq,
60+
V: Default,
61+
{
62+
let pos = self.0.iter().position(|(key, _)| &k == key).unwrap_or_else(|| {
63+
let pos = self.0.len();
64+
self.0.push((k, V::default()));
65+
pos
66+
});
67+
&mut self.0[pos].1
68+
}
69+
5670
/// Returns the any value corresponding to the supplied predicate filter.
5771
///
5872
/// The supplied predicate will be applied to each (key, value) pair and it will return a

compiler/rustc_lint/src/levels.rs

Lines changed: 110 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ use rustc_ast_pretty::pprust;
55
use rustc_data_structures::fx::FxHashMap;
66
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, DiagnosticMessage, MultiSpan};
77
use rustc_hir as hir;
8-
use rustc_hir::{intravisit, HirId};
8+
use rustc_hir::intravisit::{self, Visitor};
9+
use rustc_hir::HirId;
910
use rustc_index::vec::IndexVec;
1011
use rustc_middle::hir::nested_filter;
1112
use rustc_middle::lint::{
@@ -115,6 +116,7 @@ fn lint_expectations(tcx: TyCtxt<'_>, (): ()) -> Vec<(LintExpectationId, LintExp
115116
specs: ShallowLintLevelMap::default(),
116117
expectations: Vec::new(),
117118
unstable_to_stable_ids: FxHashMap::default(),
119+
empty: FxHashMap::default(),
118120
},
119121
warn_about_weird_lints: false,
120122
store,
@@ -130,25 +132,39 @@ fn lint_expectations(tcx: TyCtxt<'_>, (): ()) -> Vec<(LintExpectationId, LintExp
130132
builder.provider.expectations
131133
}
132134

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 {
134137
let store = unerased_lint_store(tcx);
135138

136139
let mut levels = LintLevelsBuilder {
137140
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+
},
139147
warn_about_weird_lints: false,
140148
store,
141149
registered_tools: &tcx.resolutions(()).registered_tools,
142150
};
143151

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());
150166

151-
levels.provider.specs
167+
specs
152168
}
153169

154170
pub struct TopDown {
@@ -181,14 +197,16 @@ struct LintLevelQueryMap<'tcx> {
181197
tcx: TyCtxt<'tcx>,
182198
cur: HirId,
183199
specs: ShallowLintLevelMap,
200+
/// Empty hash map to simplify code.
201+
empty: FxHashMap<LintId, LevelAndSource>,
184202
}
185203

186204
impl LintLevelsProvider for LintLevelQueryMap<'_> {
187205
fn current_specs(&self) -> &FxHashMap<LintId, LevelAndSource> {
188-
&self.specs.specs
206+
self.specs.specs.get(&self.cur.local_id).unwrap_or(&self.empty)
189207
}
190208
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)
192210
}
193211
fn get_lint_level(&self, lint: &'static Lint, _: &Session) -> LevelAndSource {
194212
self.specs.lint_level_id_at_node(self.tcx, LintId::of(lint), self.cur)
@@ -201,15 +219,18 @@ struct QueryMapExpectationsWrapper<'tcx> {
201219
specs: ShallowLintLevelMap,
202220
expectations: Vec<(LintExpectationId, LintExpectation)>,
203221
unstable_to_stable_ids: FxHashMap<LintExpectationId, LintExpectationId>,
222+
/// Empty hash map to simplify code.
223+
empty: FxHashMap<LintId, LevelAndSource>,
204224
}
205225

206226
impl LintLevelsProvider for QueryMapExpectationsWrapper<'_> {
207227
fn current_specs(&self) -> &FxHashMap<LintId, LevelAndSource> {
208-
&self.specs.specs
228+
self.specs.specs.get(&self.cur.local_id).unwrap_or(&self.empty)
209229
}
210230
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
213234
}
214235
fn get_lint_level(&self, lint: &'static Lint, _: &Session) -> LevelAndSource {
215236
self.specs.lint_level_id_at_node(self.tcx, LintId::of(lint), self.cur)
@@ -229,13 +250,86 @@ impl LintLevelsProvider for QueryMapExpectationsWrapper<'_> {
229250
}
230251
}
231252

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+
232325
impl<'tcx> LintLevelsBuilder<'_, QueryMapExpectationsWrapper<'tcx>> {
233326
fn add_id(&mut self, hir_id: HirId) {
327+
self.provider.cur = hir_id;
234328
self.add(self.provider.tcx.hir().attrs(hir_id), hir_id == hir::CRATE_HIR_ID, Some(hir_id));
235329
}
236330
}
237331

238-
impl<'tcx> intravisit::Visitor<'tcx> for LintLevelsBuilder<'_, QueryMapExpectationsWrapper<'tcx>> {
332+
impl<'tcx> Visitor<'tcx> for LintLevelsBuilder<'_, QueryMapExpectationsWrapper<'tcx>> {
239333
type NestedFilter = nested_filter::All;
240334

241335
fn nested_visit_map(&mut self) -> Self::Map {

compiler/rustc_middle/src/lint.rs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
use std::cmp;
22

33
use rustc_data_structures::fx::FxHashMap;
4+
use rustc_data_structures::vec_map::VecMap;
45
use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, MultiSpan};
5-
use rustc_hir::HirId;
6+
use rustc_hir::{HirId, ItemLocalId};
67
use rustc_session::lint::{
78
builtin::{self, FORBIDDEN_LINT_GROUPS},
89
FutureIncompatibilityReason, Level, Lint, LintId,
@@ -62,7 +63,7 @@ pub type LevelAndSource = (Level, LintLevelSource);
6263
/// by the attributes for *a single HirId*.
6364
#[derive(Default, Debug, HashStable)]
6465
pub struct ShallowLintLevelMap {
65-
pub specs: FxHashMap<LintId, LevelAndSource>,
66+
pub specs: VecMap<ItemLocalId, FxHashMap<LintId, LevelAndSource>>,
6667
}
6768

6869
/// From an initial level and source, verify the effect of special annotations:
@@ -116,19 +117,30 @@ impl ShallowLintLevelMap {
116117
/// Perform a deep probe in the HIR tree looking for the actual level for the lint.
117118
/// This lint level is not usable for diagnostics, it needs to be corrected by
118119
/// `reveal_actual_level` beforehand.
120+
#[instrument(level = "trace", skip(self, tcx), ret)]
119121
fn probe_for_lint_level(
120122
&self,
121123
tcx: TyCtxt<'_>,
122124
id: LintId,
123125
start: HirId,
124126
) -> (Option<Level>, LintLevelSource) {
125-
if let Some(&(level, src)) = self.specs.get(&id) {
127+
if let Some(map) = self.specs.get(&start.local_id)
128+
&& let Some(&(level, src)) = map.get(&id)
129+
{
126130
return (Some(level), src);
127131
}
128132

133+
let mut owner = start.owner;
134+
let mut specs = &self.specs;
135+
129136
for parent in tcx.hir().parent_id_iter(start) {
130-
let specs = tcx.shallow_lint_levels_on(parent);
131-
if let Some(&(level, src)) = specs.specs.get(&id) {
137+
if parent.owner != owner {
138+
owner = parent.owner;
139+
specs = &tcx.shallow_lint_levels_on(owner).specs;
140+
}
141+
if let Some(map) = specs.get(&parent.local_id)
142+
&& let Some(&(level, src)) = map.get(&id)
143+
{
132144
return (Some(level), src);
133145
}
134146
}
@@ -137,6 +149,7 @@ impl ShallowLintLevelMap {
137149
}
138150

139151
/// Fetch and return the user-visible lint level for the given lint at the given HirId.
152+
#[instrument(level = "trace", skip(self, tcx), ret)]
140153
pub fn lint_level_id_at_node(
141154
&self,
142155
tcx: TyCtxt<'_>,
@@ -154,7 +167,7 @@ impl ShallowLintLevelMap {
154167
impl TyCtxt<'_> {
155168
/// Fetch and return the user-visible lint level for the given lint at the given HirId.
156169
pub fn lint_level_at_node(self, lint: &'static Lint, id: HirId) -> (Level, LintLevelSource) {
157-
self.shallow_lint_levels_on(id).lint_level_id_at_node(self, LintId::of(lint), id)
170+
self.shallow_lint_levels_on(id.owner).lint_level_id_at_node(self, LintId::of(lint), id)
158171
}
159172

160173
/// Walks upwards from `id` to find a node which might change lint levels with attributes.

compiler/rustc_middle/src/query/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -274,9 +274,10 @@ rustc_queries! {
274274
separate_provide_extern
275275
}
276276

277-
query shallow_lint_levels_on(key: HirId) -> rustc_middle::lint::ShallowLintLevelMap {
277+
query shallow_lint_levels_on(key: hir::OwnerId) -> rustc_middle::lint::ShallowLintLevelMap {
278+
eval_always // fetches `resolutions`
278279
arena_cache
279-
desc { |tcx| "looking up lint levels for `{}`", key }
280+
desc { |tcx| "looking up lint levels for `{}`", tcx.def_path_str(key.to_def_id()) }
280281
}
281282

282283
query lint_expectations(_: ()) -> Vec<(LintExpectationId, LintExpectation)> {

compiler/rustc_middle/src/ty/query.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ use rustc_errors::ErrorGuaranteed;
4444
use rustc_hir as hir;
4545
use rustc_hir::def::DefKind;
4646
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId};
47-
use rustc_hir::hir_id::{HirId, OwnerId};
47+
use rustc_hir::hir_id::OwnerId;
4848
use rustc_hir::lang_items::{LangItem, LanguageItems};
4949
use rustc_hir::{Crate, ItemLocalId, TraitCandidate};
5050
use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec};

0 commit comments

Comments
 (0)