about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_lint/src/context.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/diagnostics.rs7
-rw-r--r--src/tools/clippy/tests/ui/track-diagnostics-clippy.rs22
-rw-r--r--src/tools/clippy/tests/ui/track-diagnostics-clippy.stderr29
4 files changed, 60 insertions, 0 deletions
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 95663204ec3..b694d3dd49b 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -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,
diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs
index dc240dd067b..8453165818b 100644
--- a/src/tools/clippy/clippy_utils/src/diagnostics.rs
+++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs
@@ -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,
diff --git a/src/tools/clippy/tests/ui/track-diagnostics-clippy.rs b/src/tools/clippy/tests/ui/track-diagnostics-clippy.rs
new file mode 100644
index 00000000000..2e67fb65efc
--- /dev/null
+++ b/src/tools/clippy/tests/ui/track-diagnostics-clippy.rs
@@ -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
+    };
+}
diff --git a/src/tools/clippy/tests/ui/track-diagnostics-clippy.stderr b/src/tools/clippy/tests/ui/track-diagnostics-clippy.stderr
new file mode 100644
index 00000000000..f3aca685417
--- /dev/null
+++ b/src/tools/clippy/tests/ui/track-diagnostics-clippy.stderr
@@ -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
+