about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/incompatible_msrv.rs45
-rw-r--r--tests/ui/incompatible_msrv.rs14
-rw-r--r--tests/ui/incompatible_msrv.stderr28
3 files changed, 55 insertions, 32 deletions
diff --git a/clippy_lints/src/incompatible_msrv.rs b/clippy_lints/src/incompatible_msrv.rs
index 9d98777c632..1fd8ecd179a 100644
--- a/clippy_lints/src/incompatible_msrv.rs
+++ b/clippy_lints/src/incompatible_msrv.rs
@@ -2,7 +2,7 @@ use clippy_config::Conf;
 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};
+use rustc_attr_data_structures::{RustcVersion, Stability, StableSince};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::{Expr, ExprKind, HirId, QPath};
 use rustc_lint::{LateContext, LateLintPass};
@@ -72,9 +72,15 @@ declare_clippy_lint! {
     "ensures that all items used in the crate are available for the current MSRV"
 }
 
+#[derive(Clone, Copy)]
+enum Availability {
+    FeatureEnabled,
+    Since(RustcVersion),
+}
+
 pub struct IncompatibleMsrv {
     msrv: Msrv,
-    is_above_msrv: FxHashMap<DefId, RustcVersion>,
+    availability_cache: FxHashMap<DefId, Availability>,
     check_in_tests: bool,
 }
 
@@ -84,35 +90,32 @@ impl IncompatibleMsrv {
     pub fn new(conf: &'static Conf) -> Self {
         Self {
             msrv: conf.msrv,
-            is_above_msrv: FxHashMap::default(),
+            availability_cache: FxHashMap::default(),
             check_in_tests: conf.check_incompatible_msrv_in_tests,
         }
     }
 
-    fn get_def_id_version(&mut self, tcx: TyCtxt<'_>, def_id: DefId) -> RustcVersion {
-        if let Some(version) = self.is_above_msrv.get(&def_id) {
-            return *version;
+    /// Returns the availability of `def_id`, whether it is enabled through a feature or
+    /// available since a given version (the default being Rust 1.0.0).
+    fn get_def_id_availability(&mut self, tcx: TyCtxt<'_>, def_id: DefId) -> Availability {
+        if let Some(availability) = self.availability_cache.get(&def_id) {
+            return *availability;
         }
-        let version = if let Some(version) = tcx
-            .lookup_stability(def_id)
-            .and_then(|stability| match stability.level {
-                StabilityLevel::Stable {
-                    since: StableSince::Version(version),
-                    ..
-                } => Some(version),
-                _ => None,
-            }) {
-            version
+        let stability = tcx.lookup_stability(def_id);
+        let version = if stability.is_some_and(|stability| tcx.features().enabled(stability.feature)) {
+            Availability::FeatureEnabled
+        } else if let Some(StableSince::Version(version)) = stability.as_ref().and_then(Stability::stable_since) {
+            Availability::Since(version)
         } else if let Some(parent_def_id) = tcx.opt_parent(def_id) {
-            self.get_def_id_version(tcx, parent_def_id)
+            self.get_def_id_availability(tcx, parent_def_id)
         } else {
-            RustcVersion {
+            Availability::Since(RustcVersion {
                 major: 1,
                 minor: 0,
                 patch: 0,
-            }
+            })
         };
-        self.is_above_msrv.insert(def_id, version);
+        self.availability_cache.insert(def_id, version);
         version
     }
 
@@ -143,7 +146,7 @@ impl IncompatibleMsrv {
 
         if (self.check_in_tests || !is_in_test(cx.tcx, node))
             && let Some(current) = self.msrv.current(cx)
-            && let version = self.get_def_id_version(cx.tcx, def_id)
+            && let Availability::Since(version) = self.get_def_id_availability(cx.tcx, def_id)
             && version > current
         {
             span_lint_and_then(
diff --git a/tests/ui/incompatible_msrv.rs b/tests/ui/incompatible_msrv.rs
index a6595dcb81e..c68c9c02dc4 100644
--- a/tests/ui/incompatible_msrv.rs
+++ b/tests/ui/incompatible_msrv.rs
@@ -1,5 +1,7 @@
 #![warn(clippy::incompatible_msrv)]
 #![feature(custom_inner_attributes)]
+#![allow(stable_features)]
+#![feature(strict_provenance)] // For use in test
 #![clippy::msrv = "1.3.0"]
 
 use std::collections::HashMap;
@@ -91,4 +93,16 @@ fn local_msrv_change_suggestion() {
     }
 }
 
+#[clippy::msrv = "1.78.0"]
+fn feature_enable_14425(ptr: *const u8) -> usize {
+    // Do not warn, because it is enabled through a feature even though
+    // it is stabilized only since Rust 1.84.0.
+    let r = ptr.addr();
+
+    // Warn about this which has been introduced in the same Rust version
+    // but is not allowed through a feature.
+    r.isqrt()
+    //~^ incompatible_msrv
+}
+
 fn main() {}
diff --git a/tests/ui/incompatible_msrv.stderr b/tests/ui/incompatible_msrv.stderr
index 18548c3ec18..b4477a02ac8 100644
--- a/tests/ui/incompatible_msrv.stderr
+++ b/tests/ui/incompatible_msrv.stderr
@@ -1,5 +1,5 @@
 error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.10.0`
-  --> tests/ui/incompatible_msrv.rs:13:39
+  --> tests/ui/incompatible_msrv.rs:15:39
    |
 LL |     assert_eq!(map.entry("poneyland").key(), &"poneyland");
    |                                       ^^^^^
@@ -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:19:11
+  --> tests/ui/incompatible_msrv.rs:21: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:23:5
+  --> tests/ui/incompatible_msrv.rs:25: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.43.0`
-  --> tests/ui/incompatible_msrv.rs:47:17
+  --> tests/ui/incompatible_msrv.rs:49:17
    |
 LL |         let _ = core::iter::once_with(|| 0);
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
 error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.43.0`
-  --> tests/ui/incompatible_msrv.rs:54:21
+  --> tests/ui/incompatible_msrv.rs:56:21
    |
 LL |             let _ = core::iter::once_with(|| $msg);
    |                     ^^^^^^^^^^^^^^^^^^^^^
@@ -37,25 +37,25 @@ 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.43.0`
-  --> tests/ui/incompatible_msrv.rs:61:13
+  --> tests/ui/incompatible_msrv.rs:63:13
    |
 LL |     assert!(core::iter::once_with(|| 0).next().is_some());
    |             ^^^^^^^^^^^^^^^^^^^^^
 
 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:74:13
+  --> tests/ui/incompatible_msrv.rs:76: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:79:13
+  --> tests/ui/incompatible_msrv.rs:81: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
+  --> tests/ui/incompatible_msrv.rs:86:17
    |
 LL |         let _ = std::iter::repeat_n((), 5);
    |                 ^^^^^^^^^^^^^^^^^^^
@@ -63,10 +63,16 @@ 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
+  --> tests/ui/incompatible_msrv.rs:91:17
    |
 LL |         let _ = std::iter::repeat_n((), 5);
    |                 ^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 10 previous errors
+error: current MSRV (Minimum Supported Rust Version) is `1.78.0` but this item is stable since `1.84.0`
+  --> tests/ui/incompatible_msrv.rs:104:7
+   |
+LL |     r.isqrt()
+   |       ^^^^^^^
+
+error: aborting due to 11 previous errors