Skip to content

Commit 34bc5c8

Browse files
committed
Move lint level computation to rustc_middle::lint.
1 parent 6977f7d commit 34bc5c8

File tree

5 files changed

+101
-102
lines changed

5 files changed

+101
-102
lines changed

compiler/rustc_lint/src/levels.rs

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ use rustc_hir::{intravisit, HirId};
99
use rustc_index::vec::IndexVec;
1010
use rustc_middle::hir::nested_filter;
1111
use rustc_middle::lint::{
12-
reveal_actual_level, struct_lint_level, LevelAndSource, LintExpectation, LintLevelQueryMap,
13-
LintLevelSource,
12+
reveal_actual_level, struct_lint_level, LevelAndSource, LintExpectation, LintLevelSource,
13+
ShallowLintLevelMap,
1414
};
1515
use rustc_middle::ty::query::Providers;
1616
use rustc_middle::ty::{RegisteredTools, TyCtxt};
@@ -99,7 +99,9 @@ fn lint_expectations(tcx: TyCtxt<'_>, (): ()) -> Vec<(LintExpectationId, LintExp
9999
let mut builder = LintLevelsBuilder {
100100
sess: tcx.sess,
101101
provider: QueryMapExpectationsWrapper {
102-
map: LintLevelQueryMap { tcx, cur: hir::CRATE_HIR_ID, specs: FxHashMap::default() },
102+
tcx,
103+
cur: hir::CRATE_HIR_ID,
104+
specs: ShallowLintLevelMap::default(),
103105
expectations: Vec::new(),
104106
unstable_to_stable_ids: FxHashMap::default(),
105107
},
@@ -117,12 +119,12 @@ fn lint_expectations(tcx: TyCtxt<'_>, (): ()) -> Vec<(LintExpectationId, LintExp
117119
builder.provider.expectations
118120
}
119121

120-
fn lint_levels_on(tcx: TyCtxt<'_>, hir_id: HirId) -> FxHashMap<LintId, LevelAndSource> {
122+
fn shallow_lint_levels_on(tcx: TyCtxt<'_>, hir_id: HirId) -> ShallowLintLevelMap {
121123
let store = unerased_lint_store(tcx);
122124

123125
let mut levels = LintLevelsBuilder {
124126
sess: tcx.sess,
125-
provider: LintLevelQueryMap { tcx, cur: hir_id, specs: FxHashMap::default() },
127+
provider: LintLevelQueryMap { tcx, cur: hir_id, specs: ShallowLintLevelMap::default() },
126128
warn_about_weird_lints: false,
127129
store,
128130
registered_tools: &tcx.resolutions(()).registered_tools,
@@ -143,12 +145,6 @@ pub struct TopDown {
143145
cur: LintStackIndex,
144146
}
145147

146-
pub struct QueryMapExpectationsWrapper<'tcx> {
147-
map: LintLevelQueryMap<'tcx>,
148-
expectations: Vec<(LintExpectationId, LintExpectation)>,
149-
unstable_to_stable_ids: FxHashMap<LintExpectationId, LintExpectationId>,
150-
}
151-
152148
pub trait LintLevelsProvider {
153149
fn current_specs(&self) -> &FxHashMap<LintId, LevelAndSource>;
154150
fn current_specs_mut(&mut self) -> &mut FxHashMap<LintId, LevelAndSource>;
@@ -170,28 +166,42 @@ impl LintLevelsProvider for TopDown {
170166
}
171167
}
172168

169+
struct LintLevelQueryMap<'tcx> {
170+
tcx: TyCtxt<'tcx>,
171+
cur: HirId,
172+
specs: ShallowLintLevelMap,
173+
}
174+
173175
impl LintLevelsProvider for LintLevelQueryMap<'_> {
174176
fn current_specs(&self) -> &FxHashMap<LintId, LevelAndSource> {
175-
&self.specs
177+
&self.specs.specs
176178
}
177179
fn current_specs_mut(&mut self) -> &mut FxHashMap<LintId, LevelAndSource> {
178-
&mut self.specs
180+
&mut self.specs.specs
179181
}
180182
fn get_lint_level(&self, lint: &'static Lint, _: &Session) -> LevelAndSource {
181-
self.lint_level(lint)
183+
self.specs.lint_level_id_at_node(self.tcx, LintId::of(lint), self.cur)
182184
}
183185
}
184186

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+
185195
impl LintLevelsProvider for QueryMapExpectationsWrapper<'_> {
186196
fn current_specs(&self) -> &FxHashMap<LintId, LevelAndSource> {
187-
&self.map.specs
197+
&self.specs.specs
188198
}
189199
fn current_specs_mut(&mut self) -> &mut FxHashMap<LintId, LevelAndSource> {
190-
self.map.specs.clear();
191-
&mut self.map.specs
200+
self.specs.specs.clear();
201+
&mut self.specs.specs
192202
}
193203
fn get_lint_level(&self, lint: &'static Lint, _: &Session) -> LevelAndSource {
194-
self.map.lint_level(lint)
204+
self.specs.lint_level_id_at_node(self.tcx, LintId::of(lint), self.cur)
195205
}
196206
fn push_expectation(&mut self, id: LintExpectationId, expectation: LintExpectation) {
197207
let LintExpectationId::Stable { attr_id: Some(attr_id), hir_id, attr_index, .. } = id else { bug!("unstable expectation id should already be mapped") };
@@ -210,19 +220,15 @@ impl LintLevelsProvider for QueryMapExpectationsWrapper<'_> {
210220

211221
impl<'tcx> LintLevelsBuilder<'_, QueryMapExpectationsWrapper<'tcx>> {
212222
fn add_id(&mut self, hir_id: HirId) {
213-
self.add(
214-
self.provider.map.tcx.hir().attrs(hir_id),
215-
hir_id == hir::CRATE_HIR_ID,
216-
Some(hir_id),
217-
);
223+
self.add(self.provider.tcx.hir().attrs(hir_id), hir_id == hir::CRATE_HIR_ID, Some(hir_id));
218224
}
219225
}
220226

221227
impl<'tcx> intravisit::Visitor<'tcx> for LintLevelsBuilder<'_, QueryMapExpectationsWrapper<'tcx>> {
222228
type NestedFilter = nested_filter::All;
223229

224230
fn nested_visit_map(&mut self) -> Self::Map {
225-
self.provider.map.tcx.hir()
231+
self.provider.tcx.hir()
226232
}
227233

228234
fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
@@ -941,6 +947,6 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
941947
}
942948
}
943949

944-
pub fn provide(providers: &mut Providers) {
945-
*providers = Providers { lint_levels_on, lint_expectations, ..*providers };
950+
pub(crate) fn provide(providers: &mut Providers) {
951+
*providers = Providers { shallow_lint_levels_on, lint_expectations, ..*providers };
946952
}

compiler/rustc_middle/src/lint.rs

Lines changed: 64 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,27 @@ impl LintLevelSource {
5656
/// A tuple of a lint level and its source.
5757
pub type LevelAndSource = (Level, LintLevelSource);
5858

59+
/// Return type for the `shallow_lint_levels_on` query.
60+
///
61+
/// This map represents the set of allowed lints and allowance levels given
62+
/// by the attributes for *a single HirId*.
63+
#[derive(Default, Debug, HashStable)]
64+
pub struct ShallowLintLevelMap {
65+
pub specs: FxHashMap<LintId, LevelAndSource>,
66+
}
67+
68+
/// From an initial level and source, verify the effect of special annotations:
69+
/// `warnings` lint level and lint caps.
70+
///
71+
/// The return of this function is suitable for diagnostics.
5972
pub fn reveal_actual_level(
6073
level: Option<Level>,
6174
src: &mut LintLevelSource,
6275
sess: &Session,
6376
lint: LintId,
64-
get_lint_id_level: impl FnOnce(LintId) -> (Option<Level>, LintLevelSource),
77+
probe_for_lint_level: impl FnOnce(LintId) -> (Option<Level>, LintLevelSource),
6578
) -> Level {
66-
// If `level` is none then we actually assume the default level for this
67-
// lint.
79+
// If `level` is none then we actually assume the default level for this lint.
6880
let mut level = level.unwrap_or_else(|| lint.lint.default_level(sess.edition()));
6981

7082
// If we're about to issue a warning, check at the last minute for any
@@ -76,7 +88,7 @@ pub fn reveal_actual_level(
7688
// and so if we turned that into an error, it'd defeat the purpose of the
7789
// future compatibility warning.
7890
if level == Level::Warn && lint != LintId::of(FORBIDDEN_LINT_GROUPS) {
79-
let (warnings_level, warnings_src) = get_lint_id_level(LintId::of(builtin::WARNINGS));
91+
let (warnings_level, warnings_src) = probe_for_lint_level(LintId::of(builtin::WARNINGS));
8092
if let Some(configured_warning_level) = warnings_level {
8193
if configured_warning_level != Level::Warn {
8294
level = configured_warning_level;
@@ -85,8 +97,7 @@ pub fn reveal_actual_level(
8597
}
8698
}
8799

88-
// Ensure that we never exceed the `--cap-lints` argument
89-
// unless the source is a --force-warn
100+
// Ensure that we never exceed the `--cap-lints` argument unless the source is a --force-warn
90101
level = if let LintLevelSource::CommandLine(_, Level::ForceWarn(_)) = src {
91102
level
92103
} else {
@@ -101,59 +112,76 @@ pub fn reveal_actual_level(
101112
level
102113
}
103114

104-
pub struct LintLevelQueryMap<'tcx> {
105-
pub tcx: TyCtxt<'tcx>,
106-
pub cur: HirId,
107-
pub specs: FxHashMap<LintId, LevelAndSource>,
108-
}
109-
110-
impl<'tcx> LintLevelQueryMap<'tcx> {
111-
pub fn lint_id_level(&self, id: LintId) -> (Option<Level>, LintLevelSource) {
112-
Self::get_lint_id_level(id, self.cur, self.tcx, &self.specs)
113-
}
114-
115-
pub fn lint_level(&self, lint: &'static Lint) -> LevelAndSource {
116-
Self::get_lint_level(LintId::of(lint), self.cur, self.tcx, &self.specs)
117-
}
118-
119-
pub fn get_lint_id_level(
115+
impl ShallowLintLevelMap {
116+
/// Perform a deep probe in the HIR tree looking for the actual level for the lint.
117+
/// This lint level is not usable for diagnostics, it needs to be corrected by
118+
/// `reveal_actual_level` beforehand.
119+
fn probe_for_lint_level(
120+
&self,
121+
tcx: TyCtxt<'_>,
120122
id: LintId,
121-
cur: HirId,
122-
tcx: TyCtxt<'tcx>,
123-
specs: &FxHashMap<LintId, LevelAndSource>,
123+
start: HirId,
124124
) -> (Option<Level>, LintLevelSource) {
125-
if let Some(&(level, src)) = specs.get(&id) {
125+
if let Some(&(level, src)) = self.specs.get(&id) {
126126
return (Some(level), src);
127127
}
128-
let mut cur = cur;
128+
let mut cur = start;
129129

130130
loop {
131131
let parent = tcx.hir().get_parent_node(cur);
132132
if cur == parent {
133133
return (None, LintLevelSource::Default);
134134
}
135-
let specs = tcx.lint_levels_on(parent);
136-
if let Some(&(level, src)) = specs.get(&id) {
135+
let specs = tcx.shallow_lint_levels_on(parent);
136+
if let Some(&(level, src)) = specs.specs.get(&id) {
137137
return (Some(level), src);
138138
}
139139
cur = parent
140140
}
141141
}
142142

143-
pub fn get_lint_level(
144-
id: LintId,
143+
/// Fetch and return the user-visible lint level for the given lint at the given HirId.
144+
pub fn lint_level_id_at_node(
145+
&self,
146+
tcx: TyCtxt<'_>,
147+
lint: LintId,
145148
cur: HirId,
146-
tcx: TyCtxt<'tcx>,
147-
specs: &FxHashMap<LintId, LevelAndSource>,
148149
) -> (Level, LintLevelSource) {
149-
let (level, mut src) = Self::get_lint_id_level(id, cur, tcx, specs);
150-
let level = reveal_actual_level(level, &mut src, tcx.sess, id, |id| {
151-
Self::get_lint_id_level(id, cur, tcx, specs)
150+
let (level, mut src) = self.probe_for_lint_level(tcx, lint, cur);
151+
let level = reveal_actual_level(level, &mut src, tcx.sess, lint, |lint| {
152+
self.probe_for_lint_level(tcx, lint, cur)
152153
});
153154
(level, src)
154155
}
155156
}
156157

158+
impl TyCtxt<'_> {
159+
/// Fetch and return the user-visible lint level for the given lint at the given HirId.
160+
pub fn lint_level_at_node(self, lint: &'static Lint, id: HirId) -> (Level, LintLevelSource) {
161+
self.shallow_lint_levels_on(id).lint_level_id_at_node(self, LintId::of(lint), id)
162+
}
163+
164+
/// Walks upwards from `id` to find a node which might change lint levels with attributes.
165+
/// It stops at `bound` and just returns it if reached.
166+
pub fn maybe_lint_level_root_bounded(self, mut id: HirId, bound: HirId) -> HirId {
167+
let hir = self.hir();
168+
loop {
169+
if id == bound {
170+
return bound;
171+
}
172+
173+
if hir.attrs(id).iter().any(|attr| Level::from_attr(attr).is_some()) {
174+
return id;
175+
}
176+
let next = hir.get_parent_node(id);
177+
if next == id {
178+
bug!("lint traversal reached the root of the crate");
179+
}
180+
id = next;
181+
}
182+
}
183+
}
184+
157185
/// This struct represents a lint expectation and holds all required information
158186
/// to emit the `unfulfilled_lint_expectations` lint if it is unfulfilled after
159187
/// the `LateLintPass` has completed.

compiler/rustc_middle/src/query/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ rustc_queries! {
274274
separate_provide_extern
275275
}
276276

277-
query lint_levels_on(key: HirId) -> FxHashMap<LintId, LevelAndSource> {
277+
query shallow_lint_levels_on(key: HirId) -> rustc_middle::lint::ShallowLintLevelMap {
278278
arena_cache
279279
desc { |tcx| "looking up lint levels for `{}`", key }
280280
}

compiler/rustc_middle/src/ty/context.rs

Lines changed: 2 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::arena::Arena;
44
use crate::dep_graph::{DepGraph, DepKindStruct};
55
use crate::hir::place::Place as HirPlace;
66
use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos};
7-
use crate::lint::{struct_lint_level, LintLevelSource};
7+
use crate::lint::struct_lint_level;
88
use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
99
use crate::middle::resolve_lifetime;
1010
use crate::middle::stability;
@@ -57,7 +57,7 @@ use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
5757
use rustc_session::config::{CrateType, OutputFilenames};
5858
use rustc_session::cstore::CrateStoreDyn;
5959
use rustc_session::errors::TargetDataLayoutErrorsWrapper;
60-
use rustc_session::lint::{Level, Lint, LintId};
60+
use rustc_session::lint::Lint;
6161
use rustc_session::Limit;
6262
use rustc_session::Session;
6363
use rustc_span::def_id::{DefPathHash, StableCrateId};
@@ -2812,41 +2812,6 @@ impl<'tcx> TyCtxt<'tcx> {
28122812
iter.intern_with(|xs| self.intern_bound_variable_kinds(xs))
28132813
}
28142814

2815-
/// Walks upwards from `id` to find a node which might change lint levels with attributes.
2816-
/// It stops at `bound` and just returns it if reached.
2817-
pub fn maybe_lint_level_root_bounded(self, mut id: HirId, bound: HirId) -> HirId {
2818-
let hir = self.hir();
2819-
loop {
2820-
if id == bound {
2821-
return bound;
2822-
}
2823-
2824-
if hir.attrs(id).iter().any(|attr| Level::from_attr(attr).is_some()) {
2825-
return id;
2826-
}
2827-
let next = hir.get_parent_node(id);
2828-
if next == id {
2829-
bug!("lint traversal reached the root of the crate");
2830-
}
2831-
id = next;
2832-
}
2833-
}
2834-
2835-
pub fn lint_level_at_node(
2836-
self,
2837-
lint: &'static Lint,
2838-
id: hir::HirId,
2839-
) -> (Level, LintLevelSource) {
2840-
let level_and_src = crate::lint::LintLevelQueryMap::get_lint_level(
2841-
LintId::of(lint),
2842-
id,
2843-
self,
2844-
self.lint_levels_on(id),
2845-
);
2846-
debug!(?id, ?level_and_src);
2847-
level_and_src
2848-
}
2849-
28502815
/// Emit a lint at `span` from a lint struct (some type that implements `DecorateLint`,
28512816
/// typically generated by `#[derive(LintDiagnostic)]`).
28522817
pub fn emit_spanned_lint(

compiler/rustc_middle/src/ty/query.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::dep_graph;
22
use crate::infer::canonical::{self, Canonical};
3-
use crate::lint::{LevelAndSource, LintExpectation};
3+
use crate::lint::LintExpectation;
44
use crate::metadata::ModChild;
55
use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
66
use crate::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
@@ -51,7 +51,7 @@ use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec};
5151
use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion};
5252
use rustc_session::cstore::{CrateDepKind, CrateSource};
5353
use rustc_session::cstore::{ExternCrate, ForeignModule, LinkagePreference, NativeLib};
54-
use rustc_session::lint::{LintExpectationId, LintId};
54+
use rustc_session::lint::LintExpectationId;
5555
use rustc_session::utils::NativeLibKind;
5656
use rustc_session::Limits;
5757
use rustc_span::symbol::Symbol;

0 commit comments

Comments
 (0)