diff options
| author | Samuel Tardieu <sam@rfc1149.net> | 2025-03-18 19:21:30 +0100 |
|---|---|---|
| committer | Samuel Tardieu <sam@rfc1149.net> | 2025-05-21 17:17:30 +0200 |
| commit | 205e313ae4904468d8d2ee6f2cb785bb91271512 (patch) | |
| tree | 5b9c0939ab721c476f2b567f1164b6614f48bdab | |
| parent | f2d49731575198637ee3bb2d83c7060c3581a512 (diff) | |
| download | rust-205e313ae4904468d8d2ee6f2cb785bb91271512.tar.gz rust-205e313ae4904468d8d2ee6f2cb785bb91271512.zip | |
Do not warn about feature-enabled items
If an item has been enabled through a feature, it will not be linted even though the MSRV is not compatible. This use case may happen when stable compilers are allowed to enable unstable features, e.g. in the Rust for Linux toolchain.
| -rw-r--r-- | clippy_lints/src/incompatible_msrv.rs | 45 | ||||
| -rw-r--r-- | tests/ui/incompatible_msrv.rs | 14 | ||||
| -rw-r--r-- | tests/ui/incompatible_msrv.stderr | 28 |
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 |
