From 1abf4418f80e21bd9cbc5bbdc6fe76df1eb5d494 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 8 Mar 2024 22:04:10 +0100 Subject: [PATCH 1/4] Add new `match_option_and_default` lint --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/lib.rs | 2 + clippy_lints/src/match_option_and_default.rs | 183 +++++++++++++++++++ 4 files changed, 187 insertions(+) create mode 100644 clippy_lints/src/match_option_and_default.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e0e14ca06ed..2a9688b4b51e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5390,6 +5390,7 @@ Released 2018-09-13 [`match_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_bool [`match_like_matches_macro`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_like_matches_macro [`match_on_vec_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_on_vec_items +[`match_option_and_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_option_and_default [`match_overlapping_arm`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_overlapping_arm [`match_ref_pats`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_ref_pats [`match_result_ok`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_result_ok diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 5e22ba22e273..b9b03862b7b9 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -312,6 +312,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::manual_strip::MANUAL_STRIP_INFO, crate::map_unit_fn::OPTION_MAP_UNIT_FN_INFO, crate::map_unit_fn::RESULT_MAP_UNIT_FN_INFO, + crate::match_option_and_default::MATCH_OPTION_AND_DEFAULT_INFO, crate::match_result_ok::MATCH_RESULT_OK_INFO, crate::matches::COLLAPSIBLE_MATCH_INFO, crate::matches::INFALLIBLE_DESTRUCTURING_MATCH_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index adafc92d8a35..589deb0e232a 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -212,6 +212,7 @@ mod manual_slice_size_calculation; mod manual_string_new; mod manual_strip; mod map_unit_fn; +mod match_option_and_default; mod match_result_ok; mod matches; mod mem_replace; @@ -1122,6 +1123,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_early_pass(|| Box::new(multiple_bound_locations::MultipleBoundLocations)); store.register_late_pass(|_| Box::new(assigning_clones::AssigningClones)); store.register_late_pass(|_| Box::new(zero_repeat_side_effects::ZeroRepeatSideEffects)); + store.register_late_pass(|_| Box::new(match_option_and_default::MatchOptionAndDefault)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/match_option_and_default.rs b/clippy_lints/src/match_option_and_default.rs new file mode 100644 index 000000000000..c39f6e93ebd8 --- /dev/null +++ b/clippy_lints/src/match_option_and_default.rs @@ -0,0 +1,183 @@ +use rustc_errors::Applicability; +use rustc_hir::def::Res; +use rustc_hir::{Arm, Expr, ExprKind, HirId, LangItem, MatchSource, Pat, PatKind, QPath}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::declare_lint_pass; +use rustc_span::sym; + +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::is_default_equivalent; +use clippy_utils::source::snippet_opt; +use clippy_utils::ty::implements_trait; + +declare_clippy_lint! { + /// ### What it does + /// Checks if a `match` or `if let` expression can be simplified using + /// `.unwrap_or_default()`. + /// + /// ### Why is this bad? + /// It can be done in one call with `.unwrap_or_default()`. + /// + /// ### Example + /// ```no_run + /// let x: Option = Some(String::new()); + /// let y: String = match x { + /// Some(v) => v, + /// None => String::new(), + /// }; + /// + /// let x: Option> = Some(Vec::new()); + /// let y: Vec = if let Some(v) = x { + /// v + /// } else { + /// Vec::new() + /// }; + /// ``` + /// Use instead: + /// ```no_run + /// let x: Option = Some(String::new()); + /// let y: String = x.unwrap_or_default(); + /// + /// let x: Option> = Some(Vec::new()); + /// let y: Vec = x.unwrap_or_default(); + /// ``` + #[clippy::version = "1.78.0"] + pub MATCH_OPTION_AND_DEFAULT, + suspicious, + "check if a `match` or `if let` can be simplified with `unwrap_or_default`" +} + +declare_lint_pass!(MatchOptionAndDefault => [MATCH_OPTION_AND_DEFAULT]); + +fn get_some<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'tcx>) -> Option { + if let PatKind::TupleStruct(QPath::Resolved(_, path), &[pat], _) = pat.kind + && let Some(def_id) = path.res.opt_def_id() + // Since it comes from a pattern binding, we need to get the parent to actually match + // against it. + && let Some(def_id) = cx.tcx.opt_parent(def_id) + && cx.tcx.lang_items().get(LangItem::OptionSome) == Some(def_id) + { + let mut bindings = Vec::new(); + pat.each_binding(|_, id, _, _| bindings.push(id)); + if let &[id] = bindings.as_slice() { + Some(id) + } else { + None + } + } else { + None + } +} + +fn get_none<'tcx>(cx: &LateContext<'tcx>, arm: &Arm<'tcx>) -> Option<&'tcx Expr<'tcx>> { + if let PatKind::Path(QPath::Resolved(_, path)) = arm.pat.kind + && let Some(def_id) = path.res.opt_def_id() + // Since it comes from a pattern binding, we need to get the parent to actually match + // against it. + && let Some(def_id) = cx.tcx.opt_parent(def_id) + && cx.tcx.lang_items().get(LangItem::OptionNone) == Some(def_id) + { + Some(arm.body) + } else if let PatKind::Wild = arm.pat.kind { + // We consider that the `Some` check will filter it out if it's not right. + Some(arm.body) + } else { + None + } +} + +fn get_some_and_none_bodies<'tcx>( + cx: &LateContext<'tcx>, + arm1: &'tcx Arm<'tcx>, + arm2: &'tcx Arm<'tcx>, +) -> Option<((&'tcx Expr<'tcx>, HirId), &'tcx Expr<'tcx>)> { + if let Some(binding_id) = get_some(cx, arm1.pat) + && let Some(body_none) = get_none(cx, arm2) + { + Some(((arm1.body, binding_id), body_none)) + } else if let Some(binding_id) = get_some(cx, arm2.pat) + && let Some(body_none) = get_none(cx, arm1) + { + Some(((arm2.body, binding_id), body_none)) + } else { + None + } +} + +fn handle_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { + let ExprKind::Match(match_expr, [arm1, arm2], MatchSource::Normal | MatchSource::ForLoopDesugar) = expr.kind else { + return false; + }; + // We don't want conditions on the arms to simplify things. + if arm1.guard.is_none() + && arm2.guard.is_none() + // We check that the returned type implements the `Default` trait. + && let match_ty = cx.typeck_results().expr_ty(expr) + && let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default) + && implements_trait(cx, match_ty, default_trait_id, &[]) + // We now get the bodies for both the `Some` and `None` arms. + && let Some(((body_some, binding_id), body_none)) = get_some_and_none_bodies(cx, arm1, arm2) + // We check that the `Some(x) => x` doesn't do anything apart "returning" the value in `Some`. + && let ExprKind::Path(QPath::Resolved(_, path)) = body_some.peel_blocks().kind + && let Res::Local(local_id) = path.res + && local_id == binding_id + // We now check the `None` arm is calling a method equivalent to `Default::default`. + && let body_none = body_none.peel_blocks() + && let ExprKind::Call(_, &[]) = body_none.kind + && is_default_equivalent(cx, body_none) + && let Some(match_expr_snippet) = snippet_opt(cx, match_expr.span) + { + span_lint_and_sugg( + cx, + MATCH_OPTION_AND_DEFAULT, + expr.span, + "match can be simplified with `.unwrap_or_default()`", + "replace it with", + format!("{match_expr_snippet}.unwrap_or_default()"), + Applicability::MachineApplicable, + ); + } + true +} + +fn handle_if_let<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { + if let ExprKind::If(cond, if_block, Some(else_expr)) = expr.kind + && let ExprKind::Let(let_) = cond.kind + && let ExprKind::Block(_, _) = else_expr.kind + // We check that the returned type implements the `Default` trait. + && let match_ty = cx.typeck_results().expr_ty(expr) + && let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default) + && implements_trait(cx, match_ty, default_trait_id, &[]) + && let Some(binding_id) = get_some(cx, let_.pat) + // We check that the `Some(x) => x` doesn't do anything apart "returning" the value in `Some`. + && let ExprKind::Path(QPath::Resolved(_, path)) = if_block.peel_blocks().kind + && let Res::Local(local_id) = path.res + && local_id == binding_id + // We now check the `None` arm is calling a method equivalent to `Default::default`. + && let body_else = else_expr.peel_blocks() + && let ExprKind::Call(_, &[]) = body_else.kind + && is_default_equivalent(cx, body_else) + && let Some(if_let_expr_snippet) = snippet_opt(cx, let_.init.span) + { + span_lint_and_sugg( + cx, + MATCH_OPTION_AND_DEFAULT, + expr.span, + "if let can be simplified with `.unwrap_or_default()`", + "replace it with", + format!("{if_let_expr_snippet}.unwrap_or_default()"), + Applicability::MachineApplicable, + ); + } +} + +impl<'tcx> LateLintPass<'tcx> for MatchOptionAndDefault { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { + if expr.span.from_expansion() { + return; + } + if !handle_match(cx, expr) { + handle_if_let(cx, expr); + } + } +} From fadb2540732b509d8cd2a146dd14d68998b79c87 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 8 Mar 2024 22:04:31 +0100 Subject: [PATCH 2/4] Add new ui test for `match_option_and_default` --- tests/ui/match_option_and_default.fixed | 19 ++++++++ tests/ui/match_option_and_default.rs | 40 +++++++++++++++++ tests/ui/match_option_and_default.stderr | 56 ++++++++++++++++++++++++ 3 files changed, 115 insertions(+) create mode 100644 tests/ui/match_option_and_default.fixed create mode 100644 tests/ui/match_option_and_default.rs create mode 100644 tests/ui/match_option_and_default.stderr diff --git a/tests/ui/match_option_and_default.fixed b/tests/ui/match_option_and_default.fixed new file mode 100644 index 000000000000..0a90ef636e8e --- /dev/null +++ b/tests/ui/match_option_and_default.fixed @@ -0,0 +1,19 @@ +#![warn(clippy::match_option_and_default)] +#![allow(clippy::unnecessary_literal_unwrap)] + +fn main() { + let x: Option> = None; + x.unwrap_or_default(); + + let x: Option> = None; + x.unwrap_or_default(); + + let x: Option = None; + x.unwrap_or_default(); + + let x: Option> = None; + x.unwrap_or_default(); + + let x: Option> = None; + x.unwrap_or_default(); +} diff --git a/tests/ui/match_option_and_default.rs b/tests/ui/match_option_and_default.rs new file mode 100644 index 000000000000..8e69ef47431b --- /dev/null +++ b/tests/ui/match_option_and_default.rs @@ -0,0 +1,40 @@ +#![warn(clippy::match_option_and_default)] +#![allow(clippy::unnecessary_literal_unwrap)] + +fn main() { + let x: Option> = None; + match x { + //~^ ERROR: match can be simplified with `.unwrap_or_default()` + Some(v) => v, + None => Vec::default(), + }; + + let x: Option> = None; + match x { + //~^ ERROR: match can be simplified with `.unwrap_or_default()` + Some(v) => v, + _ => Vec::default(), + }; + + let x: Option = None; + match x { + //~^ ERROR: match can be simplified with `.unwrap_or_default()` + Some(v) => v, + None => String::new(), + }; + + let x: Option> = None; + match x { + //~^ ERROR: match can be simplified with `.unwrap_or_default()` + None => Vec::default(), + Some(v) => v, + }; + + let x: Option> = None; + if let Some(v) = x { + //~^ ERROR: if let can be simplified with `.unwrap_or_default()` + v + } else { + Vec::default() + }; +} diff --git a/tests/ui/match_option_and_default.stderr b/tests/ui/match_option_and_default.stderr new file mode 100644 index 000000000000..86d7294f95a8 --- /dev/null +++ b/tests/ui/match_option_and_default.stderr @@ -0,0 +1,56 @@ +error: match can be simplified with `.unwrap_or_default()` + --> tests/ui/match_option_and_default.rs:6:5 + | +LL | / match x { +LL | | +LL | | Some(v) => v, +LL | | None => Vec::default(), +LL | | }; + | |_____^ help: replace it with: `x.unwrap_or_default()` + | + = note: `-D clippy::match-option-and-default` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::match_option_and_default)]` + +error: match can be simplified with `.unwrap_or_default()` + --> tests/ui/match_option_and_default.rs:13:5 + | +LL | / match x { +LL | | +LL | | Some(v) => v, +LL | | _ => Vec::default(), +LL | | }; + | |_____^ help: replace it with: `x.unwrap_or_default()` + +error: match can be simplified with `.unwrap_or_default()` + --> tests/ui/match_option_and_default.rs:20:5 + | +LL | / match x { +LL | | +LL | | Some(v) => v, +LL | | None => String::new(), +LL | | }; + | |_____^ help: replace it with: `x.unwrap_or_default()` + +error: match can be simplified with `.unwrap_or_default()` + --> tests/ui/match_option_and_default.rs:27:5 + | +LL | / match x { +LL | | +LL | | None => Vec::default(), +LL | | Some(v) => v, +LL | | }; + | |_____^ help: replace it with: `x.unwrap_or_default()` + +error: if let can be simplified with `.unwrap_or_default()` + --> tests/ui/match_option_and_default.rs:34:5 + | +LL | / if let Some(v) = x { +LL | | +LL | | v +LL | | } else { +LL | | Vec::default() +LL | | }; + | |_____^ help: replace it with: `x.unwrap_or_default()` + +error: aborting due to 5 previous errors + From b0f358fd3ce5897c43c706c7e87491a4ff081943 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 8 Mar 2024 22:04:17 +0100 Subject: [PATCH 3/4] Update ui test --- tests/ui/manual_let_else.rs | 3 +- tests/ui/manual_let_else.stderr | 62 +++++++++++++++--------------- tests/ui/manual_unwrap_or.fixed | 7 +++- tests/ui/manual_unwrap_or.rs | 7 +++- tests/ui/manual_unwrap_or.stderr | 28 +++++++------- tests/ui/match_result_ok.fixed | 2 +- tests/ui/match_result_ok.rs | 2 +- tests/ui/option_if_let_else.fixed | 3 +- tests/ui/option_if_let_else.rs | 3 +- tests/ui/option_if_let_else.stderr | 50 ++++++++++++------------ tests/ui/option_option.rs | 2 +- tests/ui/single_match.fixed | 3 +- tests/ui/single_match.rs | 3 +- tests/ui/single_match.stderr | 36 ++++++++--------- 14 files changed, 113 insertions(+), 98 deletions(-) diff --git a/tests/ui/manual_let_else.rs b/tests/ui/manual_let_else.rs index 1fb252e3f97b..2b36c3f3c2fb 100644 --- a/tests/ui/manual_let_else.rs +++ b/tests/ui/manual_let_else.rs @@ -8,7 +8,8 @@ clippy::never_loop, clippy::needless_if, clippy::diverging_sub_expression, - clippy::single_match + clippy::single_match, + clippy::manual_unwrap_or_default )] #![warn(clippy::manual_let_else)] //@no-rustfix diff --git a/tests/ui/manual_let_else.stderr b/tests/ui/manual_let_else.stderr index 7012c6b88914..55a410982adf 100644 --- a/tests/ui/manual_let_else.stderr +++ b/tests/ui/manual_let_else.stderr @@ -1,5 +1,5 @@ error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:28:5 + --> tests/ui/manual_let_else.rs:29:5 | LL | let v = if let Some(v_some) = g() { v_some } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { return };` @@ -8,7 +8,7 @@ LL | let v = if let Some(v_some) = g() { v_some } else { return }; = help: to override `-D warnings` add `#[allow(clippy::manual_let_else)]` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:31:5 + --> tests/ui/manual_let_else.rs:32:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -26,7 +26,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:38:5 + --> tests/ui/manual_let_else.rs:39:5 | LL | / let v = if let Some(v) = g() { LL | | @@ -47,25 +47,25 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:50:9 + --> tests/ui/manual_let_else.rs:51:9 | LL | let v = if let Some(v_some) = g() { v_some } else { continue }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { continue };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:52:9 + --> tests/ui/manual_let_else.rs:53:9 | LL | let v = if let Some(v_some) = g() { v_some } else { break }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { break };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:57:5 + --> tests/ui/manual_let_else.rs:58:5 | LL | let v = if let Some(v_some) = g() { v_some } else { panic!() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { panic!() };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:61:5 + --> tests/ui/manual_let_else.rs:62:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -83,7 +83,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:69:5 + --> tests/ui/manual_let_else.rs:70:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -101,7 +101,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:77:5 + --> tests/ui/manual_let_else.rs:78:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -121,7 +121,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:86:5 + --> tests/ui/manual_let_else.rs:87:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -141,7 +141,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:95:5 + --> tests/ui/manual_let_else.rs:96:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -168,7 +168,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:111:5 + --> tests/ui/manual_let_else.rs:112:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -190,7 +190,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:122:5 + --> tests/ui/manual_let_else.rs:123:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -217,7 +217,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:138:5 + --> tests/ui/manual_let_else.rs:139:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -239,7 +239,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:149:5 + --> tests/ui/manual_let_else.rs:150:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -257,7 +257,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:157:5 + --> tests/ui/manual_let_else.rs:158:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -278,7 +278,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:167:5 + --> tests/ui/manual_let_else.rs:168:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -299,7 +299,7 @@ LL + } }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:177:5 + --> tests/ui/manual_let_else.rs:178:5 | LL | / let v = if let Some(v_some) = g() { LL | | @@ -328,7 +328,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:195:5 + --> tests/ui/manual_let_else.rs:196:5 | LL | / let (v, w) = if let Some(v_some) = g().map(|v| (v, 42)) { LL | | @@ -346,7 +346,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:203:5 + --> tests/ui/manual_let_else.rs:204:5 | LL | / let (w, S { v }) = if let (Some(v_some), w_some) = (g().map(|_| S { v: 0 }), 0) { LL | | @@ -364,7 +364,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:213:13 + --> tests/ui/manual_let_else.rs:214:13 | LL | let $n = if let Some(v) = $e { v } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some($n) = g() else { return };` @@ -375,19 +375,19 @@ LL | create_binding_if_some!(w, g()); = note: this error originates in the macro `create_binding_if_some` (in Nightly builds, run with -Z macro-backtrace for more info) error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:222:5 + --> tests/ui/manual_let_else.rs:223:5 | LL | let v = if let Variant::A(a, 0) = e() { a } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::A(v, 0) = e() else { return };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:226:5 + --> tests/ui/manual_let_else.rs:227:5 | LL | let mut v = if let Variant::B(b) = e() { b } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::B(mut v) = e() else { return };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:231:5 + --> tests/ui/manual_let_else.rs:232:5 | LL | / let v = if let Ok(Some(Variant::B(b))) | Err(Some(Variant::A(b, _))) = nested { LL | | @@ -405,19 +405,19 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:238:5 + --> tests/ui/manual_let_else.rs:239:5 | LL | let v = if let Variant::A(.., a) = e() { a } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Variant::A(.., v) = e() else { return };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:242:5 + --> tests/ui/manual_let_else.rs:243:5 | LL | let w = if let (Some(v), ()) = (g(), ()) { v } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let (Some(w), ()) = (g(), ()) else { return };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:246:5 + --> tests/ui/manual_let_else.rs:247:5 | LL | / let w = if let Some(S { v: x }) = Some(S { v: 0 }) { LL | | @@ -435,7 +435,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:254:5 + --> tests/ui/manual_let_else.rs:255:5 | LL | / let v = if let Some(S { v: x }) = Some(S { v: 0 }) { LL | | @@ -453,7 +453,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:262:5 + --> tests/ui/manual_let_else.rs:263:5 | LL | / let (x, S { v }, w) = if let Some(U { v, w, x }) = None::>> { LL | | @@ -471,7 +471,7 @@ LL + }; | error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:379:5 + --> tests/ui/manual_let_else.rs:380:5 | LL | / let _ = match ff { LL | | @@ -481,7 +481,7 @@ LL | | }; | |______^ help: consider writing: `let Some(_) = ff else { macro_call!() };` error: this could be rewritten as `let...else` - --> tests/ui/manual_let_else.rs:456:9 + --> tests/ui/manual_let_else.rs:457:9 | LL | let v = if let Some(v_some) = g() { v_some } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some(v) = g() else { return };` diff --git a/tests/ui/manual_unwrap_or.fixed b/tests/ui/manual_unwrap_or.fixed index 737d4c90dca4..dffd44b6a7c1 100644 --- a/tests/ui/manual_unwrap_or.fixed +++ b/tests/ui/manual_unwrap_or.fixed @@ -1,5 +1,10 @@ #![allow(dead_code)] -#![allow(unused_variables, clippy::unnecessary_wraps, clippy::unnecessary_literal_unwrap)] +#![allow( + unused_variables, + clippy::unnecessary_wraps, + clippy::unnecessary_literal_unwrap, + clippy::manual_unwrap_or_default +)] fn option_unwrap_or() { // int case diff --git a/tests/ui/manual_unwrap_or.rs b/tests/ui/manual_unwrap_or.rs index f59fb87529f8..67427132c1a8 100644 --- a/tests/ui/manual_unwrap_or.rs +++ b/tests/ui/manual_unwrap_or.rs @@ -1,5 +1,10 @@ #![allow(dead_code)] -#![allow(unused_variables, clippy::unnecessary_wraps, clippy::unnecessary_literal_unwrap)] +#![allow( + unused_variables, + clippy::unnecessary_wraps, + clippy::unnecessary_literal_unwrap, + clippy::manual_unwrap_or_default +)] fn option_unwrap_or() { // int case diff --git a/tests/ui/manual_unwrap_or.stderr b/tests/ui/manual_unwrap_or.stderr index 511b79881ac3..33a099680ce0 100644 --- a/tests/ui/manual_unwrap_or.stderr +++ b/tests/ui/manual_unwrap_or.stderr @@ -1,5 +1,5 @@ error: this pattern reimplements `Option::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:6:5 + --> tests/ui/manual_unwrap_or.rs:11:5 | LL | / match Some(1) { LL | | Some(i) => i, @@ -11,7 +11,7 @@ LL | | }; = help: to override `-D warnings` add `#[allow(clippy::manual_unwrap_or)]` error: this pattern reimplements `Option::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:12:5 + --> tests/ui/manual_unwrap_or.rs:17:5 | LL | / match Some(1) { LL | | None => 42, @@ -20,7 +20,7 @@ LL | | }; | |_____^ help: replace with: `Some(1).unwrap_or(42)` error: this pattern reimplements `Option::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:18:5 + --> tests/ui/manual_unwrap_or.rs:23:5 | LL | / match Some(1) { LL | | Some(i) => i, @@ -29,7 +29,7 @@ LL | | }; | |_____^ help: replace with: `Some(1).unwrap_or(1 + 42)` error: this pattern reimplements `Option::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:25:5 + --> tests/ui/manual_unwrap_or.rs:30:5 | LL | / match Some(1) { LL | | Some(i) => i, @@ -50,7 +50,7 @@ LL ~ }); | error: this pattern reimplements `Option::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:35:5 + --> tests/ui/manual_unwrap_or.rs:40:5 | LL | / match Some("Bob") { LL | | Some(i) => i, @@ -59,7 +59,7 @@ LL | | }; | |_____^ help: replace with: `Some("Bob").unwrap_or("Alice")` error: this pattern reimplements `Result::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:85:5 + --> tests/ui/manual_unwrap_or.rs:90:5 | LL | / match Ok::(1) { LL | | Ok(i) => i, @@ -68,7 +68,7 @@ LL | | }; | |_____^ help: replace with: `Ok::(1).unwrap_or(42)` error: this pattern reimplements `Result::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:92:5 + --> tests/ui/manual_unwrap_or.rs:97:5 | LL | / match a { LL | | Ok(i) => i, @@ -77,7 +77,7 @@ LL | | }; | |_____^ help: replace with: `a.unwrap_or(42)` error: this pattern reimplements `Result::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:98:5 + --> tests/ui/manual_unwrap_or.rs:103:5 | LL | / match Ok(1) as Result { LL | | Ok(i) => i, @@ -86,7 +86,7 @@ LL | | }; | |_____^ help: replace with: `(Ok(1) as Result).unwrap_or(42)` error: this pattern reimplements `Option::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:111:5 + --> tests/ui/manual_unwrap_or.rs:116:5 | LL | / match s.method() { LL | | Some(i) => i, @@ -95,7 +95,7 @@ LL | | }; | |_____^ help: replace with: `s.method().unwrap_or(42)` error: this pattern reimplements `Result::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:117:5 + --> tests/ui/manual_unwrap_or.rs:122:5 | LL | / match Ok::(1) { LL | | Err(_) => 42, @@ -104,7 +104,7 @@ LL | | }; | |_____^ help: replace with: `Ok::(1).unwrap_or(42)` error: this pattern reimplements `Result::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:123:5 + --> tests/ui/manual_unwrap_or.rs:128:5 | LL | / match Ok::(1) { LL | | Ok(i) => i, @@ -113,7 +113,7 @@ LL | | }; | |_____^ help: replace with: `Ok::(1).unwrap_or(1 + 42)` error: this pattern reimplements `Result::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:130:5 + --> tests/ui/manual_unwrap_or.rs:135:5 | LL | / match Ok::(1) { LL | | Ok(i) => i, @@ -134,7 +134,7 @@ LL ~ }); | error: this pattern reimplements `Result::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:140:5 + --> tests/ui/manual_unwrap_or.rs:145:5 | LL | / match Ok::<&str, &str>("Bob") { LL | | Ok(i) => i, @@ -143,7 +143,7 @@ LL | | }; | |_____^ help: replace with: `Ok::<&str, &str>("Bob").unwrap_or("Alice")` error: this pattern reimplements `Option::unwrap_or` - --> tests/ui/manual_unwrap_or.rs:200:17 + --> tests/ui/manual_unwrap_or.rs:205:17 | LL | let _ = match some_macro!() { | _________________^ diff --git a/tests/ui/match_result_ok.fixed b/tests/ui/match_result_ok.fixed index 8d7cddc0ad74..76b26f5e4386 100644 --- a/tests/ui/match_result_ok.fixed +++ b/tests/ui/match_result_ok.fixed @@ -1,6 +1,6 @@ #![warn(clippy::match_result_ok)] #![allow(dead_code)] -#![allow(clippy::boxed_local, clippy::uninlined_format_args)] +#![allow(clippy::boxed_local, clippy::uninlined_format_args, clippy::manual_unwrap_or_default)] // Checking `if` cases diff --git a/tests/ui/match_result_ok.rs b/tests/ui/match_result_ok.rs index 9a18b813aca3..d6f2475ba79c 100644 --- a/tests/ui/match_result_ok.rs +++ b/tests/ui/match_result_ok.rs @@ -1,6 +1,6 @@ #![warn(clippy::match_result_ok)] #![allow(dead_code)] -#![allow(clippy::boxed_local, clippy::uninlined_format_args)] +#![allow(clippy::boxed_local, clippy::uninlined_format_args, clippy::manual_unwrap_or_default)] // Checking `if` cases diff --git a/tests/ui/option_if_let_else.fixed b/tests/ui/option_if_let_else.fixed index d443334bb059..eeab801b7da8 100644 --- a/tests/ui/option_if_let_else.fixed +++ b/tests/ui/option_if_let_else.fixed @@ -3,7 +3,8 @@ clippy::ref_option_ref, clippy::equatable_if_let, clippy::let_unit_value, - clippy::redundant_locals + clippy::redundant_locals, + clippy::manual_unwrap_or_default )] fn bad1(string: Option<&str>) -> (bool, &str) { diff --git a/tests/ui/option_if_let_else.rs b/tests/ui/option_if_let_else.rs index 317c35bf8427..3e5b96d7c316 100644 --- a/tests/ui/option_if_let_else.rs +++ b/tests/ui/option_if_let_else.rs @@ -3,7 +3,8 @@ clippy::ref_option_ref, clippy::equatable_if_let, clippy::let_unit_value, - clippy::redundant_locals + clippy::redundant_locals, + clippy::manual_unwrap_or_default )] fn bad1(string: Option<&str>) -> (bool, &str) { diff --git a/tests/ui/option_if_let_else.stderr b/tests/ui/option_if_let_else.stderr index a794dca762f1..f5359a0c34f9 100644 --- a/tests/ui/option_if_let_else.stderr +++ b/tests/ui/option_if_let_else.stderr @@ -1,5 +1,5 @@ error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:10:5 + --> tests/ui/option_if_let_else.rs:11:5 | LL | / if let Some(x) = string { LL | | (true, x) @@ -12,19 +12,19 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::option_if_let_else)]` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:28:13 + --> tests/ui/option_if_let_else.rs:29:13 | LL | let _ = if let Some(s) = *string { s.len() } else { 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `string.map_or(0, |s| s.len())` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:29:13 + --> tests/ui/option_if_let_else.rs:30:13 | LL | let _ = if let Some(s) = &num { s } else { &0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:30:13 + --> tests/ui/option_if_let_else.rs:31:13 | LL | let _ = if let Some(s) = &mut num { | _____________^ @@ -44,13 +44,13 @@ LL ~ }); | error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:36:13 + --> tests/ui/option_if_let_else.rs:37:13 | LL | let _ = if let Some(ref s) = num { s } else { &0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.as_ref().map_or(&0, |s| s)` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:37:13 + --> tests/ui/option_if_let_else.rs:38:13 | LL | let _ = if let Some(mut s) = num { | _____________^ @@ -70,7 +70,7 @@ LL ~ }); | error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:43:13 + --> tests/ui/option_if_let_else.rs:44:13 | LL | let _ = if let Some(ref mut s) = num { | _____________^ @@ -90,7 +90,7 @@ LL ~ }); | error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:52:5 + --> tests/ui/option_if_let_else.rs:53:5 | LL | / if let Some(x) = arg { LL | | let y = x * x; @@ -109,7 +109,7 @@ LL + }) | error: use Option::map_or_else instead of an if let/else - --> tests/ui/option_if_let_else.rs:65:13 + --> tests/ui/option_if_let_else.rs:66:13 | LL | let _ = if let Some(x) = arg { | _____________^ @@ -121,7 +121,7 @@ LL | | }; | |_____^ help: try: `arg.map_or_else(side_effect, |x| x)` error: use Option::map_or_else instead of an if let/else - --> tests/ui/option_if_let_else.rs:74:13 + --> tests/ui/option_if_let_else.rs:75:13 | LL | let _ = if let Some(x) = arg { | _____________^ @@ -144,7 +144,7 @@ LL ~ }, |x| x * x * x * x); | error: use Option::map_or_else instead of an if let/else - --> tests/ui/option_if_let_else.rs:107:13 + --> tests/ui/option_if_let_else.rs:108:13 | LL | / if let Some(idx) = s.find('.') { LL | | vec![s[..idx].to_string(), s[idx..].to_string()] @@ -154,7 +154,7 @@ LL | | } | |_____________^ help: try: `s.find('.').map_or_else(|| vec![s.to_string()], |idx| vec![s[..idx].to_string(), s[idx..].to_string()])` error: use Option::map_or_else instead of an if let/else - --> tests/ui/option_if_let_else.rs:118:5 + --> tests/ui/option_if_let_else.rs:119:5 | LL | / if let Ok(binding) = variable { LL | | println!("Ok {binding}"); @@ -177,13 +177,13 @@ LL + }) | error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:142:13 + --> tests/ui/option_if_let_else.rs:143:13 | LL | let _ = if let Some(x) = optional { x + 2 } else { 5 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `optional.map_or(5, |x| x + 2)` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:152:13 + --> tests/ui/option_if_let_else.rs:153:13 | LL | let _ = if let Some(x) = Some(0) { | _____________^ @@ -205,13 +205,13 @@ LL ~ }); | error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:180:13 + --> tests/ui/option_if_let_else.rs:181:13 | LL | let _ = if let Some(x) = Some(0) { s.len() + x } else { s.len() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(0).map_or(s.len(), |x| s.len() + x)` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:184:13 + --> tests/ui/option_if_let_else.rs:185:13 | LL | let _ = if let Some(x) = Some(0) { | _____________^ @@ -231,7 +231,7 @@ LL ~ }); | error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:223:13 + --> tests/ui/option_if_let_else.rs:224:13 | LL | let _ = match s { | _____________^ @@ -241,7 +241,7 @@ LL | | }; | |_____^ help: try: `s.map_or(1, |string| string.len())` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:227:13 + --> tests/ui/option_if_let_else.rs:228:13 | LL | let _ = match Some(10) { | _____________^ @@ -251,7 +251,7 @@ LL | | }; | |_____^ help: try: `Some(10).map_or(5, |a| a + 1)` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:233:13 + --> tests/ui/option_if_let_else.rs:234:13 | LL | let _ = match res { | _____________^ @@ -261,7 +261,7 @@ LL | | }; | |_____^ help: try: `res.map_or(1, |a| a + 1)` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:237:13 + --> tests/ui/option_if_let_else.rs:238:13 | LL | let _ = match res { | _____________^ @@ -271,13 +271,13 @@ LL | | }; | |_____^ help: try: `res.map_or(1, |a| a + 1)` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:241:13 + --> tests/ui/option_if_let_else.rs:242:13 | LL | let _ = if let Ok(a) = res { a + 1 } else { 5 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `res.map_or(5, |a| a + 1)` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:258:17 + --> tests/ui/option_if_let_else.rs:259:17 | LL | let _ = match initial { | _________________^ @@ -287,7 +287,7 @@ LL | | }; | |_________^ help: try: `initial.as_ref().map_or(42, |value| do_something(value))` error: use Option::map_or instead of an if let/else - --> tests/ui/option_if_let_else.rs:265:17 + --> tests/ui/option_if_let_else.rs:266:17 | LL | let _ = match initial { | _________________^ @@ -297,7 +297,7 @@ LL | | }; | |_________^ help: try: `initial.as_mut().map_or(42, |value| do_something2(value))` error: use Option::map_or_else instead of an if let/else - --> tests/ui/option_if_let_else.rs:288:24 + --> tests/ui/option_if_let_else.rs:289:24 | LL | let mut _hashmap = if let Some(hm) = &opt { | ________________________^ @@ -308,7 +308,7 @@ LL | | }; | |_____^ help: try: `opt.as_ref().map_or_else(HashMap::new, |hm| hm.clone())` error: use Option::map_or_else instead of an if let/else - --> tests/ui/option_if_let_else.rs:294:19 + --> tests/ui/option_if_let_else.rs:295:19 | LL | let mut _hm = if let Some(hm) = &opt { hm.clone() } else { new_map!() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.as_ref().map_or_else(|| new_map!(), |hm| hm.clone())` diff --git a/tests/ui/option_option.rs b/tests/ui/option_option.rs index 2f6e4d761454..7dda139c88ec 100644 --- a/tests/ui/option_option.rs +++ b/tests/ui/option_option.rs @@ -1,7 +1,7 @@ //@compile-flags: -Zdeduplicate-diagnostics=yes #![deny(clippy::option_option)] -#![allow(clippy::unnecessary_wraps)] +#![allow(clippy::unnecessary_wraps, clippy::match_option_and_default)] const C: Option> = None; //~^ ERROR: consider using `Option` instead of `Option>` or a custom enum if diff --git a/tests/ui/single_match.fixed b/tests/ui/single_match.fixed index 6df64eb40535..a7cb43e14465 100644 --- a/tests/ui/single_match.fixed +++ b/tests/ui/single_match.fixed @@ -6,7 +6,8 @@ clippy::uninlined_format_args, clippy::needless_if, clippy::redundant_guards, - clippy::redundant_pattern_matching + clippy::redundant_pattern_matching, + clippy::manual_unwrap_or_default )] fn dummy() {} diff --git a/tests/ui/single_match.rs b/tests/ui/single_match.rs index 4f005f4e04f5..09db497dcd8b 100644 --- a/tests/ui/single_match.rs +++ b/tests/ui/single_match.rs @@ -6,7 +6,8 @@ clippy::uninlined_format_args, clippy::needless_if, clippy::redundant_guards, - clippy::redundant_pattern_matching + clippy::redundant_pattern_matching, + clippy::manual_unwrap_or_default )] fn dummy() {} diff --git a/tests/ui/single_match.stderr b/tests/ui/single_match.stderr index 651d0b4911d9..f7abf996be74 100644 --- a/tests/ui/single_match.stderr +++ b/tests/ui/single_match.stderr @@ -1,5 +1,5 @@ error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:16:5 + --> tests/ui/single_match.rs:17:5 | LL | / match x { LL | | Some(y) => { @@ -19,7 +19,7 @@ LL ~ }; | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:24:5 + --> tests/ui/single_match.rs:25:5 | LL | / match x { LL | | // Note the missing block braces. @@ -31,7 +31,7 @@ LL | | } | |_____^ help: try: `if let Some(y) = x { println!("{:?}", y) }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:33:5 + --> tests/ui/single_match.rs:34:5 | LL | / match z { LL | | (2..=3, 7..=9) => dummy(), @@ -40,7 +40,7 @@ LL | | }; | |_____^ help: try: `if let (2..=3, 7..=9) = z { dummy() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:62:5 + --> tests/ui/single_match.rs:63:5 | LL | / match x { LL | | Some(y) => dummy(), @@ -49,7 +49,7 @@ LL | | }; | |_____^ help: try: `if let Some(y) = x { dummy() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:67:5 + --> tests/ui/single_match.rs:68:5 | LL | / match y { LL | | Ok(y) => dummy(), @@ -58,7 +58,7 @@ LL | | }; | |_____^ help: try: `if let Ok(y) = y { dummy() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:74:5 + --> tests/ui/single_match.rs:75:5 | LL | / match c { LL | | Cow::Borrowed(..) => dummy(), @@ -67,7 +67,7 @@ LL | | }; | |_____^ help: try: `if let Cow::Borrowed(..) = c { dummy() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> tests/ui/single_match.rs:95:5 + --> tests/ui/single_match.rs:96:5 | LL | / match x { LL | | "test" => println!(), @@ -76,7 +76,7 @@ LL | | } | |_____^ help: try: `if x == "test" { println!() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> tests/ui/single_match.rs:108:5 + --> tests/ui/single_match.rs:109:5 | LL | / match x { LL | | Foo::A => println!(), @@ -85,7 +85,7 @@ LL | | } | |_____^ help: try: `if x == Foo::A { println!() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> tests/ui/single_match.rs:114:5 + --> tests/ui/single_match.rs:115:5 | LL | / match x { LL | | FOO_C => println!(), @@ -94,7 +94,7 @@ LL | | } | |_____^ help: try: `if x == FOO_C { println!() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> tests/ui/single_match.rs:119:5 + --> tests/ui/single_match.rs:120:5 | LL | / match &&x { LL | | Foo::A => println!(), @@ -103,7 +103,7 @@ LL | | } | |_____^ help: try: `if x == Foo::A { println!() }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> tests/ui/single_match.rs:125:5 + --> tests/ui/single_match.rs:126:5 | LL | / match &x { LL | | Foo::A => println!(), @@ -112,7 +112,7 @@ LL | | } | |_____^ help: try: `if x == &Foo::A { println!() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:142:5 + --> tests/ui/single_match.rs:143:5 | LL | / match x { LL | | Bar::A => println!(), @@ -121,7 +121,7 @@ LL | | } | |_____^ help: try: `if let Bar::A = x { println!() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:150:5 + --> tests/ui/single_match.rs:151:5 | LL | / match x { LL | | None => println!(), @@ -130,7 +130,7 @@ LL | | }; | |_____^ help: try: `if let None = x { println!() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:172:5 + --> tests/ui/single_match.rs:173:5 | LL | / match x { LL | | (Some(_), _) => {}, @@ -139,7 +139,7 @@ LL | | } | |_____^ help: try: `if let (Some(_), _) = x {}` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:178:5 + --> tests/ui/single_match.rs:179:5 | LL | / match x { LL | | (Some(E::V), _) => todo!(), @@ -148,7 +148,7 @@ LL | | } | |_____^ help: try: `if let (Some(E::V), _) = x { todo!() }` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:184:5 + --> tests/ui/single_match.rs:185:5 | LL | / match (Some(42), Some(E::V), Some(42)) { LL | | (.., Some(E::V), _) => {}, @@ -157,7 +157,7 @@ LL | | } | |_____^ help: try: `if let (.., Some(E::V), _) = (Some(42), Some(E::V), Some(42)) {}` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:256:5 + --> tests/ui/single_match.rs:257:5 | LL | / match bar { LL | | Some(v) => unsafe { @@ -177,7 +177,7 @@ LL + } } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:264:5 + --> tests/ui/single_match.rs:265:5 | LL | / match bar { LL | | #[rustfmt::skip] From 98ac5f1e8cf9aaf2690665bb87f4af4135084e65 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 10 Mar 2024 01:12:15 +0100 Subject: [PATCH 4/4] Rename into `manual_unwrap_or_default` --- CHANGELOG.md | 2 +- clippy_lints/src/declared_lints.rs | 2 +- clippy_lints/src/lib.rs | 4 ++-- ..._and_default.rs => manual_unwrap_or_default.rs} | 12 +++++------- ...efault.fixed => manual_unwrap_or_default.fixed} | 2 +- ..._and_default.rs => manual_unwrap_or_default.rs} | 2 +- ...ault.stderr => manual_unwrap_or_default.stderr} | 14 +++++++------- tests/ui/option_option.rs | 2 +- 8 files changed, 19 insertions(+), 21 deletions(-) rename clippy_lints/src/{match_option_and_default.rs => manual_unwrap_or_default.rs} (95%) rename tests/ui/{match_option_and_default.fixed => manual_unwrap_or_default.fixed} (90%) rename tests/ui/{match_option_and_default.rs => manual_unwrap_or_default.rs} (95%) rename tests/ui/{match_option_and_default.stderr => manual_unwrap_or_default.stderr} (76%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a9688b4b51e..3bb3ef15d5b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5377,6 +5377,7 @@ Released 2018-09-13 [`manual_swap`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_swap [`manual_try_fold`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_try_fold [`manual_unwrap_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_unwrap_or +[`manual_unwrap_or_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_unwrap_or_default [`manual_while_let_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_while_let_some [`many_single_char_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names [`map_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_clone @@ -5390,7 +5391,6 @@ Released 2018-09-13 [`match_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_bool [`match_like_matches_macro`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_like_matches_macro [`match_on_vec_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_on_vec_items -[`match_option_and_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_option_and_default [`match_overlapping_arm`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_overlapping_arm [`match_ref_pats`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_ref_pats [`match_result_ok`]: https://rust-lang.github.io/rust-clippy/master/index.html#match_result_ok diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index b9b03862b7b9..0ccfd34494ea 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -310,9 +310,9 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::manual_slice_size_calculation::MANUAL_SLICE_SIZE_CALCULATION_INFO, crate::manual_string_new::MANUAL_STRING_NEW_INFO, crate::manual_strip::MANUAL_STRIP_INFO, + crate::manual_unwrap_or_default::MANUAL_UNWRAP_OR_DEFAULT_INFO, crate::map_unit_fn::OPTION_MAP_UNIT_FN_INFO, crate::map_unit_fn::RESULT_MAP_UNIT_FN_INFO, - crate::match_option_and_default::MATCH_OPTION_AND_DEFAULT_INFO, crate::match_result_ok::MATCH_RESULT_OK_INFO, crate::matches::COLLAPSIBLE_MATCH_INFO, crate::matches::INFALLIBLE_DESTRUCTURING_MATCH_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 589deb0e232a..70292d3440ed 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -211,8 +211,8 @@ mod manual_retain; mod manual_slice_size_calculation; mod manual_string_new; mod manual_strip; +mod manual_unwrap_or_default; mod map_unit_fn; -mod match_option_and_default; mod match_result_ok; mod matches; mod mem_replace; @@ -1123,7 +1123,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_early_pass(|| Box::new(multiple_bound_locations::MultipleBoundLocations)); store.register_late_pass(|_| Box::new(assigning_clones::AssigningClones)); store.register_late_pass(|_| Box::new(zero_repeat_side_effects::ZeroRepeatSideEffects)); - store.register_late_pass(|_| Box::new(match_option_and_default::MatchOptionAndDefault)); + store.register_late_pass(|_| Box::new(manual_unwrap_or_default::ManualUnwrapOrDefault)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/match_option_and_default.rs b/clippy_lints/src/manual_unwrap_or_default.rs similarity index 95% rename from clippy_lints/src/match_option_and_default.rs rename to clippy_lints/src/manual_unwrap_or_default.rs index c39f6e93ebd8..ddaf97c463ae 100644 --- a/clippy_lints/src/match_option_and_default.rs +++ b/clippy_lints/src/manual_unwrap_or_default.rs @@ -42,12 +42,12 @@ declare_clippy_lint! { /// let y: Vec = x.unwrap_or_default(); /// ``` #[clippy::version = "1.78.0"] - pub MATCH_OPTION_AND_DEFAULT, + pub MANUAL_UNWRAP_OR_DEFAULT, suspicious, "check if a `match` or `if let` can be simplified with `unwrap_or_default`" } -declare_lint_pass!(MatchOptionAndDefault => [MATCH_OPTION_AND_DEFAULT]); +declare_lint_pass!(ManualUnwrapOrDefault => [MANUAL_UNWRAP_OR_DEFAULT]); fn get_some<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'tcx>) -> Option { if let PatKind::TupleStruct(QPath::Resolved(_, path), &[pat], _) = pat.kind @@ -123,13 +123,12 @@ fn handle_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { && local_id == binding_id // We now check the `None` arm is calling a method equivalent to `Default::default`. && let body_none = body_none.peel_blocks() - && let ExprKind::Call(_, &[]) = body_none.kind && is_default_equivalent(cx, body_none) && let Some(match_expr_snippet) = snippet_opt(cx, match_expr.span) { span_lint_and_sugg( cx, - MATCH_OPTION_AND_DEFAULT, + MANUAL_UNWRAP_OR_DEFAULT, expr.span, "match can be simplified with `.unwrap_or_default()`", "replace it with", @@ -155,13 +154,12 @@ fn handle_if_let<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { && local_id == binding_id // We now check the `None` arm is calling a method equivalent to `Default::default`. && let body_else = else_expr.peel_blocks() - && let ExprKind::Call(_, &[]) = body_else.kind && is_default_equivalent(cx, body_else) && let Some(if_let_expr_snippet) = snippet_opt(cx, let_.init.span) { span_lint_and_sugg( cx, - MATCH_OPTION_AND_DEFAULT, + MANUAL_UNWRAP_OR_DEFAULT, expr.span, "if let can be simplified with `.unwrap_or_default()`", "replace it with", @@ -171,7 +169,7 @@ fn handle_if_let<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { } } -impl<'tcx> LateLintPass<'tcx> for MatchOptionAndDefault { +impl<'tcx> LateLintPass<'tcx> for ManualUnwrapOrDefault { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { if expr.span.from_expansion() { return; diff --git a/tests/ui/match_option_and_default.fixed b/tests/ui/manual_unwrap_or_default.fixed similarity index 90% rename from tests/ui/match_option_and_default.fixed rename to tests/ui/manual_unwrap_or_default.fixed index 0a90ef636e8e..c8456805ee6e 100644 --- a/tests/ui/match_option_and_default.fixed +++ b/tests/ui/manual_unwrap_or_default.fixed @@ -1,4 +1,4 @@ -#![warn(clippy::match_option_and_default)] +#![warn(clippy::manual_unwrap_or_default)] #![allow(clippy::unnecessary_literal_unwrap)] fn main() { diff --git a/tests/ui/match_option_and_default.rs b/tests/ui/manual_unwrap_or_default.rs similarity index 95% rename from tests/ui/match_option_and_default.rs rename to tests/ui/manual_unwrap_or_default.rs index 8e69ef47431b..820717be53a8 100644 --- a/tests/ui/match_option_and_default.rs +++ b/tests/ui/manual_unwrap_or_default.rs @@ -1,4 +1,4 @@ -#![warn(clippy::match_option_and_default)] +#![warn(clippy::manual_unwrap_or_default)] #![allow(clippy::unnecessary_literal_unwrap)] fn main() { diff --git a/tests/ui/match_option_and_default.stderr b/tests/ui/manual_unwrap_or_default.stderr similarity index 76% rename from tests/ui/match_option_and_default.stderr rename to tests/ui/manual_unwrap_or_default.stderr index 86d7294f95a8..f4eb65835884 100644 --- a/tests/ui/match_option_and_default.stderr +++ b/tests/ui/manual_unwrap_or_default.stderr @@ -1,5 +1,5 @@ error: match can be simplified with `.unwrap_or_default()` - --> tests/ui/match_option_and_default.rs:6:5 + --> tests/ui/manual_unwrap_or_default.rs:6:5 | LL | / match x { LL | | @@ -8,11 +8,11 @@ LL | | None => Vec::default(), LL | | }; | |_____^ help: replace it with: `x.unwrap_or_default()` | - = note: `-D clippy::match-option-and-default` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::match_option_and_default)]` + = note: `-D clippy::manual-unwrap-or-default` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::manual_unwrap_or_default)]` error: match can be simplified with `.unwrap_or_default()` - --> tests/ui/match_option_and_default.rs:13:5 + --> tests/ui/manual_unwrap_or_default.rs:13:5 | LL | / match x { LL | | @@ -22,7 +22,7 @@ LL | | }; | |_____^ help: replace it with: `x.unwrap_or_default()` error: match can be simplified with `.unwrap_or_default()` - --> tests/ui/match_option_and_default.rs:20:5 + --> tests/ui/manual_unwrap_or_default.rs:20:5 | LL | / match x { LL | | @@ -32,7 +32,7 @@ LL | | }; | |_____^ help: replace it with: `x.unwrap_or_default()` error: match can be simplified with `.unwrap_or_default()` - --> tests/ui/match_option_and_default.rs:27:5 + --> tests/ui/manual_unwrap_or_default.rs:27:5 | LL | / match x { LL | | @@ -42,7 +42,7 @@ LL | | }; | |_____^ help: replace it with: `x.unwrap_or_default()` error: if let can be simplified with `.unwrap_or_default()` - --> tests/ui/match_option_and_default.rs:34:5 + --> tests/ui/manual_unwrap_or_default.rs:34:5 | LL | / if let Some(v) = x { LL | | diff --git a/tests/ui/option_option.rs b/tests/ui/option_option.rs index 7dda139c88ec..8eb75428ca57 100644 --- a/tests/ui/option_option.rs +++ b/tests/ui/option_option.rs @@ -1,7 +1,7 @@ //@compile-flags: -Zdeduplicate-diagnostics=yes #![deny(clippy::option_option)] -#![allow(clippy::unnecessary_wraps, clippy::match_option_and_default)] +#![allow(clippy::unnecessary_wraps, clippy::manual_unwrap_or_default)] const C: Option> = None; //~^ ERROR: consider using `Option` instead of `Option>` or a custom enum if