|
1 | 1 | use std::cmp; |
2 | 2 |
|
3 | 3 | use rustc_data_structures::fx::FxHashMap; |
4 | | -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; |
5 | 4 | use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, MultiSpan}; |
6 | 5 | use rustc_hir::HirId; |
7 | | -use rustc_index::vec::IndexVec; |
8 | | -use rustc_query_system::ich::StableHashingContext; |
9 | 6 | use rustc_session::lint::{ |
10 | 7 | builtin::{self, FORBIDDEN_LINT_GROUPS}, |
11 | | - FutureIncompatibilityReason, Level, Lint, LintExpectationId, LintId, |
| 8 | + FutureIncompatibilityReason, Level, Lint, LintId, |
12 | 9 | }; |
13 | 10 | use rustc_session::Session; |
14 | 11 | use rustc_span::hygiene::MacroKind; |
@@ -59,159 +56,51 @@ impl LintLevelSource { |
59 | 56 | /// A tuple of a lint level and its source. |
60 | 57 | pub type LevelAndSource = (Level, LintLevelSource); |
61 | 58 |
|
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; |
114 | 84 | } |
115 | 85 | } |
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 |
131 | 86 | } |
132 | 87 |
|
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 | + }; |
148 | 95 |
|
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); |
170 | 99 | } |
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 | | -} |
185 | 100 |
|
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 |
202 | 102 | } |
203 | 103 |
|
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 | | -} |
215 | 104 | pub struct LintLevelQueryMap<'tcx> { |
216 | 105 | pub tcx: TyCtxt<'tcx>, |
217 | 106 | pub cur: HirId, |
@@ -258,7 +147,7 @@ impl<'tcx> LintLevelQueryMap<'tcx> { |
258 | 147 | specs: &FxHashMap<LintId, LevelAndSource>, |
259 | 148 | ) -> (Level, LintLevelSource) { |
260 | 149 | 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| { |
262 | 151 | Self::get_lint_id_level(id, cur, tcx, specs) |
263 | 152 | }); |
264 | 153 | (level, src) |
|
0 commit comments