From c60222dc12c4868a4aee439d98b007b129edc4cb Mon Sep 17 00:00:00 2001 From: darklyspaced Date: Mon, 26 Jun 2023 13:39:45 +0800 Subject: [PATCH] changed the msrv to 1.70 to suggest `is_some_and` if the msrv is not >= 1.70 then the `map_or` is suggested instead of `is_some_and` (even when `unwrap_or` returns false) --- clippy_lints/src/methods/mod.rs | 2 +- .../src/methods/option_map_unwrap_or.rs | 12 ++++++--- clippy_utils/src/msrvs.rs | 1 + tests/ui/map_unwrap_or.rs | 14 ++++++++++ tests/ui/map_unwrap_or.stderr | 26 ++++++++++++++++++- 5 files changed, 49 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 403fac123..b1d3b61ae 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -3906,7 +3906,7 @@ impl Methods { manual_saturating_arithmetic::check(cx, expr, lhs, rhs, u_arg, &arith["checked_".len()..]); }, Some(("map", m_recv, [m_arg], span, _)) => { - option_map_unwrap_or::check(cx, expr, m_recv, m_arg, recv, u_arg, span); + option_map_unwrap_or::check(cx, expr, m_recv, m_arg, recv, u_arg, span, &self.msrv); }, Some(("then_some", t_recv, [t_arg], _, _)) => { obfuscated_if_else::check(cx, expr, t_recv, t_arg, u_arg); diff --git a/clippy_lints/src/methods/option_map_unwrap_or.rs b/clippy_lints/src/methods/option_map_unwrap_or.rs index 6a4d288ab..4387090fe 100644 --- a/clippy_lints/src/methods/option_map_unwrap_or.rs +++ b/clippy_lints/src/methods/option_map_unwrap_or.rs @@ -1,4 +1,5 @@ use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::is_copy; use clippy_utils::ty::is_type_diagnostic_item; @@ -27,6 +28,7 @@ pub(super) fn check<'tcx>( unwrap_recv: &rustc_hir::Expr<'_>, unwrap_arg: &'tcx rustc_hir::Expr<'_>, map_span: Span, + msrv: &Msrv, ) { // lint if the caller of `map()` is an `Option` if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Option) { @@ -75,10 +77,12 @@ pub(super) fn check<'tcx>( } let mut suggest_is_some_and = false; - // argument to `unwrap_or` is false; should suggest using `is_some_and` - if let ExprKind::Lit(unwrap_lit) = &unwrap_arg.kind { - if let rustc_ast::LitKind::Bool(false) = unwrap_lit.node { - suggest_is_some_and = true; + // argument to `unwrap_or` is false & is_some_and is stabilised; should suggest using `is_some_and` + if msrv.meets(msrvs::OPT_IS_SOME_AND) { + if let ExprKind::Lit(unwrap_lit) = &unwrap_arg.kind { + if let rustc_ast::LitKind::Bool(false) = unwrap_lit.node { + suggest_is_some_and = true; + } } } diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs index 0a4c3418a..1541dc839 100644 --- a/clippy_utils/src/msrvs.rs +++ b/clippy_utils/src/msrvs.rs @@ -19,6 +19,7 @@ macro_rules! msrv_aliases { // names may refer to stabilized feature flags or library items msrv_aliases! { + 1,70,0 { OPT_IS_SOME_AND } 1,68,0 { PATH_MAIN_SEPARATOR_STR } 1,65,0 { LET_ELSE, POINTER_CAST_CONSTNESS } 1,62,0 { BOOL_THEN_SOME, DEFAULT_ENUM_ATTRIBUTE } diff --git a/tests/ui/map_unwrap_or.rs b/tests/ui/map_unwrap_or.rs index 51b88c7cf..bb36cb2c5 100644 --- a/tests/ui/map_unwrap_or.rs +++ b/tests/ui/map_unwrap_or.rs @@ -99,6 +99,20 @@ fn msrv_1_41() { let _ = res.map(|x| x + 1).unwrap_or_else(|_e| 0); } +#[clippy::msrv = "1.69"] +fn msrv_1_69() { + let opt: Option = Some(1); + + let _ = opt.map(|x| x > 5).unwrap_or(false); +} + +#[clippy::msrv = "1.70"] +fn msrv_1_70() { + let opt: Option = Some(1); + + let _ = opt.map(|x| x > 5).unwrap_or(false); +} + mod issue_10579 { // Different variations of the same issue. fn v1() { diff --git a/tests/ui/map_unwrap_or.stderr b/tests/ui/map_unwrap_or.stderr index 6f23d2e4f..9f4a4a9ae 100644 --- a/tests/ui/map_unwrap_or.stderr +++ b/tests/ui/map_unwrap_or.stderr @@ -164,5 +164,29 @@ error: called `map().unwrap_or_else()` on a `Result` value. This can be do LL | let _ = res.map(|x| x + 1).unwrap_or_else(|_e| 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `res.map_or_else(|_e| 0, |x| x + 1)` -error: aborting due to 13 previous errors +error: called `map().unwrap_or()` on an `Option` value. This can be done more directly by calling `map_or(, )` instead + --> $DIR/map_unwrap_or.rs:106:13 + | +LL | let _ = opt.map(|x| x > 5).unwrap_or(false); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `map_or(, )` instead + | +LL - let _ = opt.map(|x| x > 5).unwrap_or(false); +LL + let _ = opt.map_or(false, |x| x > 5); + | + +error: called `map().unwrap_or(false)` on an `Option` value. This can be done more directly by calling `is_some_and()` instead + --> $DIR/map_unwrap_or.rs:113:13 + | +LL | let _ = opt.map(|x| x > 5).unwrap_or(false); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use `is_some_and()` instead + | +LL - let _ = opt.map(|x| x > 5).unwrap_or(false); +LL + let _ = opt.is_some_and(|x| x > 5); + | + +error: aborting due to 15 previous errors