Rollup merge of #143306 - samueltardieu:track-clippy-lints-emission, r=petrochenkov

Add `track_caller` attributes to trace origin of Clippy lints

This allows the use of `-Z track-diagnostics` to see the origin of Clippy lints emission, as is already the case for lints coming from rustc.
This commit is contained in:
Matthias Krüger 2025-07-02 19:29:39 +02:00 committed by GitHub
commit bc8bcc7e8a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 60 additions and 0 deletions

View file

@ -504,6 +504,7 @@ pub trait LintContext {
///
/// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature
#[rustc_lint_diagnostics]
#[track_caller]
fn opt_span_lint<S: Into<MultiSpan>>(
&self,
lint: &'static Lint,
@ -542,6 +543,7 @@ pub trait LintContext {
///
/// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature
#[rustc_lint_diagnostics]
#[track_caller]
fn span_lint<S: Into<MultiSpan>>(
&self,
lint: &'static Lint,

View file

@ -98,6 +98,7 @@ fn validate_diag(diag: &Diag<'_, impl EmissionGuarantee>) {
/// 17 | std::mem::forget(seven);
/// | ^^^^^^^^^^^^^^^^^^^^^^^
/// ```
#[track_caller]
pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: impl Into<MultiSpan>, msg: impl Into<DiagMessage>) {
#[expect(clippy::disallowed_methods)]
cx.span_lint(lint, sp, |diag| {
@ -143,6 +144,7 @@ pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: impl Into<Mult
/// |
/// = help: consider using `f64::NAN` if you would like a constant representing NaN
/// ```
#[track_caller]
pub fn span_lint_and_help<T: LintContext>(
cx: &T,
lint: &'static Lint,
@ -203,6 +205,7 @@ pub fn span_lint_and_help<T: LintContext>(
/// 10 | forget(&SomeStruct);
/// | ^^^^^^^^^^^
/// ```
#[track_caller]
pub fn span_lint_and_note<T: LintContext>(
cx: &T,
lint: &'static Lint,
@ -244,6 +247,7 @@ pub fn span_lint_and_note<T: LintContext>(
/// If you're unsure which function you should use, you can test if the `#[expect]` attribute works
/// where you would expect it to.
/// If it doesn't, you likely need to use [`span_lint_hir_and_then`] instead.
#[track_caller]
pub fn span_lint_and_then<C, S, M, F>(cx: &C, lint: &'static Lint, sp: S, msg: M, f: F)
where
C: LintContext,
@ -286,6 +290,7 @@ where
/// Instead, use this function and also pass the `HirId` of `<expr_1>`, which will let
/// the compiler check lint level attributes at the place of the expression and
/// the `#[allow]` will work.
#[track_caller]
pub fn span_lint_hir(cx: &LateContext<'_>, lint: &'static Lint, hir_id: HirId, sp: Span, msg: impl Into<DiagMessage>) {
#[expect(clippy::disallowed_methods)]
cx.tcx.node_span_lint(lint, hir_id, sp, |diag| {
@ -321,6 +326,7 @@ pub fn span_lint_hir(cx: &LateContext<'_>, lint: &'static Lint, hir_id: HirId, s
/// Instead, use this function and also pass the `HirId` of `<expr_1>`, which will let
/// the compiler check lint level attributes at the place of the expression and
/// the `#[allow]` will work.
#[track_caller]
pub fn span_lint_hir_and_then(
cx: &LateContext<'_>,
lint: &'static Lint,
@ -374,6 +380,7 @@ pub fn span_lint_hir_and_then(
/// = note: `-D fold-any` implied by `-D warnings`
/// ```
#[cfg_attr(not(debug_assertions), expect(clippy::collapsible_span_lint_calls))]
#[track_caller]
pub fn span_lint_and_sugg<T: LintContext>(
cx: &T,
lint: &'static Lint,

View file

@ -0,0 +1,22 @@
//@compile-flags: -Z track-diagnostics
//@no-rustfix
// Normalize the emitted location so this doesn't need
// updating everytime someone adds or removes a line.
//@normalize-stderr-test: ".rs:\d+:\d+" -> ".rs:LL:CC"
#![warn(clippy::let_and_return, clippy::unnecessary_cast)]
fn main() {
// Check the provenance of a lint sent through `LintContext::span_lint()`
let a = 3u32;
let b = a as u32;
//~^ unnecessary_cast
// Check the provenance of a lint sent through `TyCtxt::node_span_lint()`
let c = {
let d = 42;
d
//~^ let_and_return
};
}

View file

@ -0,0 +1,29 @@
error: casting to the same type is unnecessary (`u32` -> `u32`)
--> tests/ui/track-diagnostics-clippy.rs:LL:CC
|
LL | let b = a as u32;
| ^^^^^^^^ help: try: `a`
-Ztrack-diagnostics: created at src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs:LL:CC
|
= note: `-D clippy::unnecessary-cast` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::unnecessary_cast)]`
error: returning the result of a `let` binding from a block
--> tests/ui/track-diagnostics-clippy.rs:LL:CC
|
LL | let d = 42;
| ----------- unnecessary `let` binding
LL | d
| ^
-Ztrack-diagnostics: created at src/tools/clippy/clippy_lints/src/returns.rs:LL:CC
|
= note: `-D clippy::let-and-return` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::let_and_return)]`
help: return the expression directly
|
LL ~
LL ~ 42
|
error: aborting due to 2 previous errors