Skip to content

Commit 9a29e16

Browse files
committed
mention lint group in default level lint note
1 parent 16ad385 commit 9a29e16

File tree

5 files changed

+99
-6
lines changed

5 files changed

+99
-6
lines changed

compiler/rustc_lint/src/context.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout};
2424
use rustc_middle::ty::print::{PrintError, PrintTraitRefExt as _, Printer, with_no_trimmed_paths};
2525
use rustc_middle::ty::{self, GenericArg, RegisteredTools, Ty, TyCtxt, TypingEnv, TypingMode};
2626
use rustc_session::lint::{FutureIncompatibleInfo, Lint, LintBuffer, LintExpectationId, LintId};
27-
use rustc_session::{LintStoreMarker, Session};
27+
use rustc_session::{DynLintStore, Session};
2828
use rustc_span::edit_distance::find_best_match_for_names;
2929
use rustc_span::{Ident, Span, Symbol, sym};
3030
use tracing::debug;
@@ -62,7 +62,13 @@ pub struct LintStore {
6262
lint_groups: FxIndexMap<&'static str, LintGroup>,
6363
}
6464

65-
impl LintStoreMarker for LintStore {}
65+
impl DynLintStore for LintStore {
66+
fn lint_groups_iter(&self) -> Box<dyn Iterator<Item = rustc_session::LintGroup> + '_> {
67+
Box::new(self.get_lint_groups().map(|(name, lints, is_externally_loaded)| {
68+
rustc_session::LintGroup { name, lints, is_externally_loaded }
69+
}))
70+
}
71+
}
6672

6773
/// The target of the `by_name` map, which accounts for renaming/deprecation.
6874
#[derive(Debug)]

compiler/rustc_middle/src/lint.rs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,11 +211,28 @@ impl LintExpectation {
211211
}
212212

213213
fn explain_lint_level_source(
214+
sess: &Session,
214215
lint: &'static Lint,
215216
level: Level,
216217
src: LintLevelSource,
217218
err: &mut Diag<'_, ()>,
218219
) {
220+
// Find the name of the lint group that contains the given lint.
221+
// Assumes the lint only belongs to one group.
222+
let lint_group_name = |lint| {
223+
let lint_groups_iter = sess.lint_groups_iter();
224+
let lint_id = LintId::of(lint);
225+
lint_groups_iter
226+
.filter(|lint_group| !lint_group.is_externally_loaded)
227+
.find(|lint_group| {
228+
lint_group
229+
.lints
230+
.iter()
231+
.find(|lint_group_lint| **lint_group_lint == lint_id)
232+
.is_some()
233+
})
234+
.map(|lint_group| lint_group.name)
235+
};
219236
let name = lint.name_lower();
220237
if let Level::Allow = level {
221238
// Do not point at `#[allow(compat_lint)]` as the reason for a compatibility lint
@@ -224,7 +241,15 @@ fn explain_lint_level_source(
224241
}
225242
match src {
226243
LintLevelSource::Default => {
227-
err.note_once(format!("`#[{}({})]` on by default", level.as_str(), name));
244+
let level_str = level.as_str();
245+
match lint_group_name(lint) {
246+
Some(group_name) => {
247+
err.note_once(format!("`#[{level_str}({name})]` (part of `#[{level_str}({group_name})]`) on by default"));
248+
}
249+
None => {
250+
err.note_once(format!("`#[{level_str}({name})]` on by default"));
251+
}
252+
}
228253
}
229254
LintLevelSource::CommandLine(lint_flag_val, orig_level) => {
230255
let flag = orig_level.to_cmd_flag();
@@ -427,7 +452,7 @@ pub fn lint_level(
427452
decorate(&mut err);
428453
}
429454

430-
explain_lint_level_source(lint, level, src, &mut err);
455+
explain_lint_level_source(sess, lint, level, src, &mut err);
431456
err.emit()
432457
}
433458
lint_level_impl(sess, lint, level, span, Box::new(decorate))

compiler/rustc_session/src/session.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ use crate::config::{
4444
SwitchWithOptPath,
4545
};
4646
use crate::filesearch::FileSearch;
47+
use crate::lint::LintId;
4748
use crate::parse::{ParseSess, add_feature_diagnostics};
4849
use crate::search_paths::SearchPath;
4950
use crate::{errors, filesearch, lint};
@@ -139,7 +140,10 @@ pub struct CompilerIO {
139140
pub temps_dir: Option<PathBuf>,
140141
}
141142

142-
pub trait LintStoreMarker: Any + DynSync + DynSend {}
143+
pub trait DynLintStore: Any + DynSync + DynSend {
144+
/// Provides a way to access lint groups without depending on `rustc_lint`
145+
fn lint_groups_iter(&self) -> Box<dyn Iterator<Item = LintGroup> + '_>;
146+
}
143147

144148
/// Represents the data associated with a compilation
145149
/// session for a single crate.
@@ -164,7 +168,7 @@ pub struct Session {
164168
pub code_stats: CodeStats,
165169

166170
/// This only ever stores a `LintStore` but we don't want a dependency on that type here.
167-
pub lint_store: Option<Arc<dyn LintStoreMarker>>,
171+
pub lint_store: Option<Arc<dyn DynLintStore>>,
168172

169173
/// Cap lint level specified by a driver specifically.
170174
pub driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
@@ -240,6 +244,12 @@ impl CodegenUnits {
240244
}
241245
}
242246

247+
pub struct LintGroup {
248+
pub name: &'static str,
249+
pub lints: Vec<LintId>,
250+
pub is_externally_loaded: bool,
251+
}
252+
243253
impl Session {
244254
pub fn miri_unleashed_feature(&self, span: Span, feature_gate: Option<Symbol>) {
245255
self.miri_unleashed_features.lock().push((span, feature_gate));
@@ -596,6 +606,13 @@ impl Session {
596606
(&*self.target.staticlib_prefix, &*self.target.staticlib_suffix)
597607
}
598608
}
609+
610+
pub fn lint_groups_iter(&self) -> Box<dyn Iterator<Item = LintGroup> + '_> {
611+
match self.lint_store {
612+
Some(ref lint_store) => lint_store.lint_groups_iter(),
613+
None => Box::new(std::iter::empty()),
614+
}
615+
}
599616
}
600617

601618
// JUSTIFICATION: defn of the suggested wrapper fns
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//@ check-pass
2+
3+
// Verify information about membership to builtin lint group is included in the lint message when
4+
// explaining lint level and source for builtin lints with default settings.
5+
//
6+
// Ideally, we'd like to use lints that are part of `unused` group as shown in the issue.
7+
// This is not possible in a ui test, because `unused` lints are enabled with `-A unused`
8+
// in such tests, and the we're testing a scenario with no modification to the default settings.
9+
10+
fn main() {
11+
// additional context is provided only if the level is not explicitly set
12+
let WrongCase = 1;
13+
//~^ WARN [non_snake_case]
14+
//~| NOTE `#[warn(non_snake_case)]` (part of `#[warn(nonstandard_style)]`) on by default
15+
16+
// unchanged message if the level is explicitly set
17+
// even if the level is the same as the default
18+
#[warn(nonstandard_style)] //~ NOTE the lint level is defined here
19+
let WrongCase = 2;
20+
//~^ WARN [non_snake_case]
21+
//~| NOTE `#[warn(non_snake_case)]` implied by `#[warn(nonstandard_style)]`
22+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
warning: variable `WrongCase` should have a snake case name
2+
--> $DIR/mention-lint-group-in-default-level-lint-note-issue-65464.rs:12:9
3+
|
4+
LL | let WrongCase = 1;
5+
| ^^^^^^^^^ help: convert the identifier to snake case: `wrong_case`
6+
|
7+
= note: `#[warn(non_snake_case)]` (part of `#[warn(nonstandard_style)]`) on by default
8+
9+
warning: variable `WrongCase` should have a snake case name
10+
--> $DIR/mention-lint-group-in-default-level-lint-note-issue-65464.rs:19:9
11+
|
12+
LL | let WrongCase = 2;
13+
| ^^^^^^^^^ help: convert the identifier to snake case: `wrong_case`
14+
|
15+
note: the lint level is defined here
16+
--> $DIR/mention-lint-group-in-default-level-lint-note-issue-65464.rs:18:12
17+
|
18+
LL | #[warn(nonstandard_style)]
19+
| ^^^^^^^^^^^^^^^^^
20+
= note: `#[warn(non_snake_case)]` implied by `#[warn(nonstandard_style)]`
21+
22+
warning: 2 warnings emitted
23+

0 commit comments

Comments
 (0)