Skip to content

Commit 41db9b1

Browse files
committed
Move code to rustc_lint.
1 parent 107170b commit 41db9b1

File tree

2 files changed

+107
-151
lines changed

2 files changed

+107
-151
lines changed

compiler/rustc_lint/src/levels.rs

Lines changed: 69 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@ use rustc_data_structures::fx::FxHashMap;
66
use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, DiagnosticMessage, MultiSpan};
77
use rustc_hir as hir;
88
use rustc_hir::{intravisit, HirId};
9+
use rustc_index::vec::IndexVec;
910
use rustc_middle::hir::nested_filter;
1011
use 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, LintLevelQueryMap,
13+
LintLevelSource,
1314
};
1415
use rustc_middle::ty::query::Providers;
1516
use rustc_middle::ty::{RegisteredTools, TyCtxt};
@@ -27,6 +28,72 @@ use crate::errors::{
2728
UnknownToolInScopedLint,
2829
};
2930

31+
#[derive(Debug)]
32+
pub struct LintLevelSets {
33+
pub list: IndexVec<LintStackIndex, LintSet>,
34+
}
35+
36+
rustc_index::newtype_index! {
37+
pub struct LintStackIndex {
38+
ENCODABLE = custom, // we don't need encoding
39+
const COMMAND_LINE = 0,
40+
}
41+
}
42+
43+
#[derive(Debug)]
44+
pub struct LintSet {
45+
// -A,-W,-D flags, a `Symbol` for the flag itself and `Level` for which
46+
// flag.
47+
pub specs: FxHashMap<LintId, LevelAndSource>,
48+
49+
pub parent: LintStackIndex,
50+
}
51+
52+
impl LintLevelSets {
53+
pub 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.get_lint_id_level(lint, idx, aux);
66+
let level = reveal_actual_level(level, &mut src, sess, lint, |id| {
67+
self.get_lint_id_level(id, idx, aux)
68+
});
69+
70+
(level, src)
71+
}
72+
73+
pub fn get_lint_id_level(
74+
&self,
75+
id: LintId,
76+
mut idx: LintStackIndex,
77+
aux: Option<&FxHashMap<LintId, LevelAndSource>>,
78+
) -> (Option<Level>, LintLevelSource) {
79+
if let Some(specs) = aux {
80+
if let Some(&(level, src)) = specs.get(&id) {
81+
return (Some(level), src);
82+
}
83+
}
84+
loop {
85+
let LintSet { ref specs, parent } = self.list[idx];
86+
if let Some(&(level, src)) = specs.get(&id) {
87+
return (Some(level), src);
88+
}
89+
if idx == COMMAND_LINE {
90+
return (None, LintLevelSource::Default);
91+
}
92+
idx = parent;
93+
}
94+
}
95+
}
96+
3097
fn lint_expectations(tcx: TyCtxt<'_>, (): ()) -> Vec<(LintExpectationId, LintExpectation)> {
3198
let store = unerased_lint_store(tcx);
3299

compiler/rustc_middle/src/lint.rs

Lines changed: 38 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
use std::cmp;
22

33
use rustc_data_structures::fx::FxHashMap;
4-
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
54
use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, MultiSpan};
65
use rustc_hir::HirId;
7-
use rustc_index::vec::IndexVec;
8-
use rustc_query_system::ich::StableHashingContext;
96
use rustc_session::lint::{
107
builtin::{self, FORBIDDEN_LINT_GROUPS},
11-
FutureIncompatibilityReason, Level, Lint, LintExpectationId, LintId,
8+
FutureIncompatibilityReason, Level, Lint, LintId,
129
};
1310
use rustc_session::Session;
1411
use rustc_span::hygiene::MacroKind;
@@ -59,159 +56,51 @@ impl LintLevelSource {
5956
/// A tuple of a lint level and its source.
6057
pub type LevelAndSource = (Level, LintLevelSource);
6158

62-
#[derive(Debug, HashStable)]
63-
pub struct LintLevelSets {
64-
pub list: IndexVec<LintStackIndex, LintSet>,
65-
}
66-
67-
rustc_index::newtype_index! {
68-
#[derive(HashStable)]
69-
pub struct LintStackIndex {
70-
const COMMAND_LINE = 0,
71-
}
72-
}
73-
74-
#[derive(Debug, HashStable)]
75-
pub struct LintSet {
76-
// -A,-W,-D flags, a `Symbol` for the flag itself and `Level` for which
77-
// flag.
78-
pub specs: FxHashMap<LintId, LevelAndSource>,
79-
80-
pub parent: LintStackIndex,
81-
}
82-
83-
impl LintLevelSets {
84-
pub fn new() -> Self {
85-
LintLevelSets { list: IndexVec::new() }
86-
}
87-
88-
pub fn actual_level(
89-
level: Option<Level>,
90-
src: &mut LintLevelSource,
91-
sess: &Session,
92-
lint: &'static Lint,
93-
get_lint_id_level: impl FnOnce(LintId) -> (Option<Level>, LintLevelSource),
94-
) -> Level {
95-
// If `level` is none then we actually assume the default level for this
96-
// lint.
97-
let mut level = level.unwrap_or_else(|| lint.default_level(sess.edition()));
98-
99-
// If we're about to issue a warning, check at the last minute for any
100-
// directives against the warnings "lint". If, for example, there's an
101-
// `allow(warnings)` in scope then we want to respect that instead.
102-
//
103-
// We exempt `FORBIDDEN_LINT_GROUPS` from this because it specifically
104-
// triggers in cases (like #80988) where you have `forbid(warnings)`,
105-
// and so if we turned that into an error, it'd defeat the purpose of the
106-
// future compatibility warning.
107-
if level == Level::Warn && LintId::of(lint) != LintId::of(FORBIDDEN_LINT_GROUPS) {
108-
let (warnings_level, warnings_src) = get_lint_id_level(LintId::of(builtin::WARNINGS));
109-
if let Some(configured_warning_level) = warnings_level {
110-
if configured_warning_level != Level::Warn {
111-
level = configured_warning_level;
112-
*src = warnings_src;
113-
}
59+
pub fn reveal_actual_level(
60+
level: Option<Level>,
61+
src: &mut LintLevelSource,
62+
sess: &Session,
63+
lint: LintId,
64+
get_lint_id_level: impl FnOnce(LintId) -> (Option<Level>, LintLevelSource),
65+
) -> Level {
66+
// If `level` is none then we actually assume the default level for this
67+
// lint.
68+
let mut level = level.unwrap_or_else(|| lint.lint.default_level(sess.edition()));
69+
70+
// If we're about to issue a warning, check at the last minute for any
71+
// directives against the warnings "lint". If, for example, there's an
72+
// `allow(warnings)` in scope then we want to respect that instead.
73+
//
74+
// We exempt `FORBIDDEN_LINT_GROUPS` from this because it specifically
75+
// triggers in cases (like #80988) where you have `forbid(warnings)`,
76+
// and so if we turned that into an error, it'd defeat the purpose of the
77+
// future compatibility warning.
78+
if level == Level::Warn && lint != LintId::of(FORBIDDEN_LINT_GROUPS) {
79+
let (warnings_level, warnings_src) = get_lint_id_level(LintId::of(builtin::WARNINGS));
80+
if let Some(configured_warning_level) = warnings_level {
81+
if configured_warning_level != Level::Warn {
82+
level = configured_warning_level;
83+
*src = warnings_src;
11484
}
11585
}
116-
117-
// Ensure that we never exceed the `--cap-lints` argument
118-
// unless the source is a --force-warn
119-
level = if let LintLevelSource::CommandLine(_, Level::ForceWarn(_)) = src {
120-
level
121-
} else {
122-
cmp::min(level, sess.opts.lint_cap.unwrap_or(Level::Forbid))
123-
};
124-
125-
if let Some(driver_level) = sess.driver_lint_caps.get(&LintId::of(lint)) {
126-
// Ensure that we never exceed driver level.
127-
level = cmp::min(*driver_level, level);
128-
}
129-
130-
level
13186
}
13287

133-
pub fn get_lint_level(
134-
&self,
135-
lint: &'static Lint,
136-
idx: LintStackIndex,
137-
aux: Option<&FxHashMap<LintId, LevelAndSource>>,
138-
sess: &Session,
139-
) -> LevelAndSource {
140-
let (level, mut src) = self.get_lint_id_level(LintId::of(lint), idx, aux);
141-
142-
let level = Self::actual_level(level, &mut src, sess, lint, |id| {
143-
self.get_lint_id_level(id, idx, aux)
144-
});
145-
146-
(level, src)
147-
}
88+
// Ensure that we never exceed the `--cap-lints` argument
89+
// unless the source is a --force-warn
90+
level = if let LintLevelSource::CommandLine(_, Level::ForceWarn(_)) = src {
91+
level
92+
} else {
93+
cmp::min(level, sess.opts.lint_cap.unwrap_or(Level::Forbid))
94+
};
14895

149-
pub fn get_lint_id_level(
150-
&self,
151-
id: LintId,
152-
mut idx: LintStackIndex,
153-
aux: Option<&FxHashMap<LintId, LevelAndSource>>,
154-
) -> (Option<Level>, LintLevelSource) {
155-
if let Some(specs) = aux {
156-
if let Some(&(level, src)) = specs.get(&id) {
157-
return (Some(level), src);
158-
}
159-
}
160-
loop {
161-
let LintSet { ref specs, parent } = self.list[idx];
162-
if let Some(&(level, src)) = specs.get(&id) {
163-
return (Some(level), src);
164-
}
165-
if idx == COMMAND_LINE {
166-
return (None, LintLevelSource::Default);
167-
}
168-
idx = parent;
169-
}
96+
if let Some(driver_level) = sess.driver_lint_caps.get(&lint) {
97+
// Ensure that we never exceed driver level.
98+
level = cmp::min(*driver_level, level);
17099
}
171-
}
172-
173-
#[derive(Debug)]
174-
pub struct LintLevelMap {
175-
/// This is a collection of lint expectations as described in RFC 2383, that
176-
/// can be fulfilled during this compilation session. This means that at least
177-
/// one expected lint is currently registered in the lint store.
178-
///
179-
/// The [`LintExpectationId`] is stored as a part of the [`Expect`](Level::Expect)
180-
/// lint level.
181-
pub lint_expectations: Vec<(LintExpectationId, LintExpectation)>,
182-
pub sets: LintLevelSets,
183-
pub id_to_set: FxHashMap<HirId, LintStackIndex>,
184-
}
185100

186-
impl LintLevelMap {
187-
/// If the `id` was previously registered with `register_id` when building
188-
/// this `LintLevelMap` this returns the corresponding lint level and source
189-
/// of the lint level for the lint provided.
190-
///
191-
/// If the `id` was not previously registered, returns `None`. If `None` is
192-
/// returned then the parent of `id` should be acquired and this function
193-
/// should be called again.
194-
pub fn level_and_source(
195-
&self,
196-
lint: &'static Lint,
197-
id: HirId,
198-
session: &Session,
199-
) -> Option<LevelAndSource> {
200-
self.id_to_set.get(&id).map(|idx| self.sets.get_lint_level(lint, *idx, None, session))
201-
}
101+
level
202102
}
203103

204-
impl<'a> HashStable<StableHashingContext<'a>> for LintLevelMap {
205-
#[inline]
206-
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
207-
let LintLevelMap { ref sets, ref id_to_set, ref lint_expectations } = *self;
208-
209-
id_to_set.hash_stable(hcx, hasher);
210-
lint_expectations.hash_stable(hcx, hasher);
211-
212-
hcx.while_hashing_spans(true, |hcx| sets.hash_stable(hcx, hasher))
213-
}
214-
}
215104
pub struct LintLevelQueryMap<'tcx> {
216105
pub tcx: TyCtxt<'tcx>,
217106
pub cur: HirId,
@@ -258,7 +147,7 @@ impl<'tcx> LintLevelQueryMap<'tcx> {
258147
specs: &FxHashMap<LintId, LevelAndSource>,
259148
) -> (Level, LintLevelSource) {
260149
let (level, mut src) = Self::get_lint_id_level(id, cur, tcx, specs);
261-
let level = LintLevelSets::actual_level(level, &mut src, tcx.sess, id.lint, |id| {
150+
let level = reveal_actual_level(level, &mut src, tcx.sess, id, |id| {
262151
Self::get_lint_id_level(id, cur, tcx, specs)
263152
});
264153
(level, src)

0 commit comments

Comments
 (0)