diff --git a/CHANGELOG.md b/CHANGELOG.md index 51441ab9fc0d..22ea3c65d897 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6360,6 +6360,7 @@ Released 2018-09-13 [`excessive-nesting-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#excessive-nesting-threshold [`future-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#future-size-threshold [`ignore-interior-mutability`]: https://doc.rust-lang.org/clippy/lint_configuration.html#ignore-interior-mutability +[`ignore-msrv-check-for`]: https://doc.rust-lang.org/clippy/lint_configuration.html#ignore-msrv-check-for [`large-error-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#large-error-threshold [`lint-inconsistent-struct-field-initializers`]: https://doc.rust-lang.org/clippy/lint_configuration.html#lint-inconsistent-struct-field-initializers [`literal-representation-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#literal-representation-threshold diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 28b613ea3295..88f782584e1f 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -603,6 +603,24 @@ A list of paths to types that should be treated as if they do not contain interi * [`mutable_key_type`](https://rust-lang.github.io/rust-clippy/master/index.html#mutable_key_type) +## `ignore-msrv-check-for` +A list of path to items that should not be checked for a compatible MSRV. This can be used to ignore +MSRV checks for code which is gated by a feature which depends on the version of the Rust compiler. + +#### Example + +```toml +# Ignore those as we use them only when our `modern_compiler` feature is active. +ignore-msrv-check-for = [ "str::split_once", "std::option::Option::as_slice" ] +``` + +**Default Value:** `[]` + +--- +**Affected lints:** +* [`incompatible_msrv`](https://rust-lang.github.io/rust-clippy/master/index.html#incompatible_msrv) + + ## `large-error-threshold` The maximum size of the `Err`-variant in a `Result` returned from a function diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index a61acbaa96bc..02794c28feb1 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -539,6 +539,17 @@ define_Conf! { /// A list of paths to types that should be treated as if they do not contain interior mutability #[lints(borrow_interior_mutable_const, declare_interior_mutable_const, ifs_same_cond, mutable_key_type)] ignore_interior_mutability: Vec = Vec::from(["bytes::Bytes".into()]), + /// A list of path to items that should not be checked for a compatible MSRV. This can be used to ignore + /// MSRV checks for code which is gated by a feature which depends on the version of the Rust compiler. + /// + /// #### Example + /// + /// ```toml + /// # Ignore those as we use them only when our `modern_compiler` feature is active. + /// ignore-msrv-check-for = [ "str::split_once", "std::option::Option::as_slice" ] + /// ``` + #[lints(incompatible_msrv)] + ignore_msrv_check_for: Vec = Vec::new(), /// The maximum size of the `Err`-variant in a `Result` returned from a function #[lints(result_large_err)] large_error_threshold: u64 = 128, diff --git a/clippy_lints/src/incompatible_msrv.rs b/clippy_lints/src/incompatible_msrv.rs index 12dfb14c454d..cfcec04608dd 100644 --- a/clippy_lints/src/incompatible_msrv.rs +++ b/clippy_lints/src/incompatible_msrv.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint; -use clippy_utils::is_in_test; use clippy_utils::msrvs::Msrv; +use clippy_utils::{def_path_def_ids, is_in_test}; use rustc_attr_parsing::{RustcVersion, StabilityLevel, StableSince}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::{Expr, ExprKind, HirId}; @@ -43,16 +43,23 @@ pub struct IncompatibleMsrv { msrv: Msrv, is_above_msrv: FxHashMap, check_in_tests: bool, + ignored_def_ids: Vec, } impl_lint_pass!(IncompatibleMsrv => [INCOMPATIBLE_MSRV]); impl IncompatibleMsrv { - pub fn new(conf: &'static Conf) -> Self { + pub fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self { + let ignored_def_ids = conf + .ignore_msrv_check_for + .iter() + .flat_map(|x| def_path_def_ids(tcx, &x.split("::").collect::>())) + .collect(); Self { msrv: conf.msrv, is_above_msrv: FxHashMap::default(), check_in_tests: conf.check_incompatible_msrv_in_tests, + ignored_def_ids, } } @@ -84,8 +91,9 @@ impl IncompatibleMsrv { } fn emit_lint_if_under_msrv(&mut self, cx: &LateContext<'_>, def_id: DefId, node: HirId, span: Span) { - if def_id.is_local() { - // We don't check local items since their MSRV is supposed to always be valid. + // We don't check local items since their MSRV is supposed to always be valid, nor ignored items + // which may be feature-gated. + if def_id.is_local() || self.ignored_def_ids.contains(&def_id) { return; } if let ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) = span.ctxt().outer_expn_data().kind { diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 3fe3cd67e167..b2b219eb0cdd 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -955,7 +955,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(|_| Box::::default()); store.register_late_pass(move |_| Box::new(pub_underscore_fields::PubUnderscoreFields::new(conf))); store.register_late_pass(move |_| Box::new(missing_const_for_thread_local::MissingConstForThreadLocal::new(conf))); - store.register_late_pass(move |_| Box::new(incompatible_msrv::IncompatibleMsrv::new(conf))); + store.register_late_pass(move |tcx| Box::new(incompatible_msrv::IncompatibleMsrv::new(tcx, conf))); store.register_late_pass(|_| Box::new(to_string_trait_impl::ToStringTraitImpl)); store.register_early_pass(|| Box::new(multiple_bound_locations::MultipleBoundLocations)); store.register_late_pass(move |_| Box::new(assigning_clones::AssigningClones::new(conf))); diff --git a/tests/ui-toml/incompatible_msrv/clippy.toml b/tests/ui-toml/incompatible_msrv/clippy.toml new file mode 100644 index 000000000000..e054a9a86de7 --- /dev/null +++ b/tests/ui-toml/incompatible_msrv/clippy.toml @@ -0,0 +1 @@ +ignore-msrv-check-for = ["str::split_once", "std::option::Option::as_slice"] diff --git a/tests/ui-toml/incompatible_msrv/incompatible_msrv.rs b/tests/ui-toml/incompatible_msrv/incompatible_msrv.rs new file mode 100644 index 000000000000..520a128fc46a --- /dev/null +++ b/tests/ui-toml/incompatible_msrv/incompatible_msrv.rs @@ -0,0 +1,18 @@ +#![warn(clippy::incompatible_msrv)] + +#[clippy::msrv = "1.46"] +fn main() { + if let Some((a, b)) = "foo:bar".split_once(":") { + println!("a = {a}, b = {b}"); + } + + let x: Option = Some(42u32); + for i in x.as_slice() { + println!("i = {i}"); + } + + if x.is_none_or(|x| x + 2 == 17) { + //~^ incompatible_msrv + println!("impossible"); + } +} diff --git a/tests/ui-toml/incompatible_msrv/incompatible_msrv.stderr b/tests/ui-toml/incompatible_msrv/incompatible_msrv.stderr new file mode 100644 index 000000000000..e04be29fc12b --- /dev/null +++ b/tests/ui-toml/incompatible_msrv/incompatible_msrv.stderr @@ -0,0 +1,11 @@ +error: current MSRV (Minimum Supported Rust Version) is `1.46.0` but this item is stable since `1.82.0` + --> tests/ui-toml/incompatible_msrv/incompatible_msrv.rs:14:10 + | +LL | if x.is_none_or(|x| x + 2 == 17) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::incompatible-msrv` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::incompatible_msrv)]` + +error: aborting due to 1 previous error + diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr index acfe739277cc..24c0593ac18d 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -48,6 +48,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect excessive-nesting-threshold future-size-threshold ignore-interior-mutability + ignore-msrv-check-for large-error-threshold lint-inconsistent-struct-field-initializers literal-representation-threshold @@ -140,6 +141,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect excessive-nesting-threshold future-size-threshold ignore-interior-mutability + ignore-msrv-check-for large-error-threshold lint-inconsistent-struct-field-initializers literal-representation-threshold @@ -232,6 +234,7 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni excessive-nesting-threshold future-size-threshold ignore-interior-mutability + ignore-msrv-check-for large-error-threshold lint-inconsistent-struct-field-initializers literal-representation-threshold