about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSamuel Tardieu <sam@rfc1149.net>2025-03-18 18:12:10 +0100
committerSamuel Tardieu <sam@rfc1149.net>2025-05-21 17:17:30 +0200
commite236bfc8d7136bbb1d1fc9143d1289297cec4ea0 (patch)
tree8dce1d4ece3a54b210dd97b3af8c5b4ad64ca162
parent96ae10e2316d6f8836c4cd06ef80b80be03e8628 (diff)
downloadrust-e236bfc8d7136bbb1d1fc9143d1289297cec4ea0.tar.gz
rust-e236bfc8d7136bbb1d1fc9143d1289297cec4ea0.zip
Add a note to `incompatible_msrv` to suggest feature gating the MSRV
The first non-MSRV-compatible item located under a `#[cfg(…)]` or
`#[cfg_attr(…)]` attribute will get an additional note suggesting
changing `#[clippy::msrv]` locally.
-rw-r--r--clippy_lints/src/incompatible_msrv.rs22
-rw-r--r--tests/ui-toml/check_incompatible_msrv_in_tests/check_incompatible_msrv_in_tests.enabled.stderr2
-rw-r--r--tests/ui/incompatible_msrv.rs18
-rw-r--r--tests/ui/incompatible_msrv.stderr34
4 files changed, 67 insertions, 9 deletions
diff --git a/clippy_lints/src/incompatible_msrv.rs b/clippy_lints/src/incompatible_msrv.rs
index 523fc4efc59..9d98777c632 100644
--- a/clippy_lints/src/incompatible_msrv.rs
+++ b/clippy_lints/src/incompatible_msrv.rs
@@ -1,5 +1,5 @@
 use clippy_config::Conf;
-use clippy_utils::diagnostics::span_lint;
+use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::is_in_test;
 use clippy_utils::msrvs::Msrv;
 use rustc_attr_data_structures::{RustcVersion, StabilityLevel, StableSince};
@@ -146,13 +146,18 @@ impl IncompatibleMsrv {
             && let version = self.get_def_id_version(cx.tcx, def_id)
             && version > current
         {
-            span_lint(
+            span_lint_and_then(
                 cx,
                 INCOMPATIBLE_MSRV,
                 span,
                 format!(
                     "current MSRV (Minimum Supported Rust Version) is `{current}` but this item is stable since `{version}`"
                 ),
+                |diag| {
+                    if is_under_cfg_attribute(cx, node) {
+                        diag.note_once("you may want to conditionally increase the MSRV considered by Clippy using the `clippy::msrv` attribute");
+                    }
+                },
             );
         }
     }
@@ -180,3 +185,16 @@ impl<'tcx> LateLintPass<'tcx> for IncompatibleMsrv {
         }
     }
 }
+
+/// Heuristic checking if the node `hir_id` is under a `#[cfg()]` or `#[cfg_attr()]`
+/// attribute.
+fn is_under_cfg_attribute(cx: &LateContext<'_>, hir_id: HirId) -> bool {
+    cx.tcx.hir_parent_id_iter(hir_id).any(|id| {
+        cx.tcx.hir_attrs(id).iter().any(|attr| {
+            matches!(
+                attr.ident().map(|ident| ident.name),
+                Some(sym::cfg_trace | sym::cfg_attr_trace)
+            )
+        })
+    })
+}
diff --git a/tests/ui-toml/check_incompatible_msrv_in_tests/check_incompatible_msrv_in_tests.enabled.stderr b/tests/ui-toml/check_incompatible_msrv_in_tests/check_incompatible_msrv_in_tests.enabled.stderr
index 8a85d38fba3..608264beb10 100644
--- a/tests/ui-toml/check_incompatible_msrv_in_tests/check_incompatible_msrv_in_tests.enabled.stderr
+++ b/tests/ui-toml/check_incompatible_msrv_in_tests/check_incompatible_msrv_in_tests.enabled.stderr
@@ -18,6 +18,8 @@ error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is
    |
 LL |         sleep(Duration::new(1, 0));
    |         ^^^^^
+   |
+   = note: you may want to conditionally increase the MSRV considered by Clippy using the `clippy::msrv` attribute
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/incompatible_msrv.rs b/tests/ui/incompatible_msrv.rs
index 99101b2bb8f..546f1661469 100644
--- a/tests/ui/incompatible_msrv.rs
+++ b/tests/ui/incompatible_msrv.rs
@@ -13,6 +13,8 @@ fn foo() {
     let mut map: HashMap<&str, u32> = HashMap::new();
     assert_eq!(map.entry("poneyland").key(), &"poneyland");
     //~^ incompatible_msrv
+    //~| NOTE: `-D clippy::incompatible-msrv` implied by `-D warnings`
+    //~| HELP: to override `-D warnings` add `#[allow(clippy::incompatible_msrv)]`
 
     if let Entry::Vacant(v) = map.entry("poneyland") {
         v.into_key();
@@ -73,4 +75,20 @@ fn issue14212() {
     //~^ ERROR: is `1.80.0` but this item is stable since `1.82.0`
 }
 
+fn local_msrv_change_suggestion() {
+    let _ = std::iter::repeat_n((), 5);
+    //~^ incompatible_msrv
+
+    #[cfg(any(test, not(test)))]
+    {
+        let _ = std::iter::repeat_n((), 5);
+        //~^ incompatible_msrv
+        //~| NOTE: you may want to conditionally increase the MSRV
+
+        // Emit the additional note only once
+        let _ = std::iter::repeat_n((), 5);
+        //~^ incompatible_msrv
+    }
+}
+
 fn main() {}
diff --git a/tests/ui/incompatible_msrv.stderr b/tests/ui/incompatible_msrv.stderr
index 5ea2bb9cc58..0a294f2f2b9 100644
--- a/tests/ui/incompatible_msrv.stderr
+++ b/tests/ui/incompatible_msrv.stderr
@@ -8,25 +8,25 @@ LL |     assert_eq!(map.entry("poneyland").key(), &"poneyland");
    = help: to override `-D warnings` add `#[allow(clippy::incompatible_msrv)]`
 
 error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.12.0`
-  --> tests/ui/incompatible_msrv.rs:18:11
+  --> tests/ui/incompatible_msrv.rs:20:11
    |
 LL |         v.into_key();
    |           ^^^^^^^^^^
 
 error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.4.0`
-  --> tests/ui/incompatible_msrv.rs:22:5
+  --> tests/ui/incompatible_msrv.rs:24:5
    |
 LL |     sleep(Duration::new(1, 0));
    |     ^^^^^
 
 error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.6.0`
-  --> tests/ui/incompatible_msrv.rs:46:9
+  --> tests/ui/incompatible_msrv.rs:48:9
    |
 LL |         core::panicking::panic("foo");
    |         ^^^^^^^^^^^^^^^^^^^^^^
 
 error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.6.0`
-  --> tests/ui/incompatible_msrv.rs:53:13
+  --> tests/ui/incompatible_msrv.rs:55:13
    |
 LL |             core::panicking::panic($msg)
    |             ^^^^^^^^^^^^^^^^^^^^^^
@@ -37,16 +37,36 @@ LL |     my_panic!("foo");
    = note: this error originates in the macro `my_panic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.6.0`
-  --> tests/ui/incompatible_msrv.rs:59:13
+  --> tests/ui/incompatible_msrv.rs:61:13
    |
 LL |     assert!(core::panicking::panic("out of luck"));
    |             ^^^^^^^^^^^^^^^^^^^^^^
 
 error: current MSRV (Minimum Supported Rust Version) is `1.80.0` but this item is stable since `1.82.0`
-  --> tests/ui/incompatible_msrv.rs:72:13
+  --> tests/ui/incompatible_msrv.rs:74:13
    |
 LL |     let _ = std::iter::repeat_n((), 5);
    |             ^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 7 previous errors
+error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.82.0`
+  --> tests/ui/incompatible_msrv.rs:79:13
+   |
+LL |     let _ = std::iter::repeat_n((), 5);
+   |             ^^^^^^^^^^^^^^^^^^^
+
+error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.82.0`
+  --> tests/ui/incompatible_msrv.rs:84:17
+   |
+LL |         let _ = std::iter::repeat_n((), 5);
+   |                 ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: you may want to conditionally increase the MSRV considered by Clippy using the `clippy::msrv` attribute
+
+error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.82.0`
+  --> tests/ui/incompatible_msrv.rs:89:17
+   |
+LL |         let _ = std::iter::repeat_n((), 5);
+   |                 ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 10 previous errors