Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 33 additions & 19 deletions clippy_lints/src/matches/match_like_matches.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
//! Lint a `match` or `if let .. { .. } else { .. }` expr that could be replaced by `matches!`

use super::REDUNDANT_PATTERN_MATCHING;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::higher::has_let_expr;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{is_lint_allowed, is_wild, span_contains_comment};
use rustc_ast::LitKind;
Expand Down Expand Up @@ -43,18 +44,23 @@ pub(crate) fn check_if_let<'tcx>(
{
ex_new = ex_inner;
}
span_lint_and_sugg(
span_lint_and_then(
cx,
MATCH_LIKE_MATCHES_MACRO,
expr.span,
"if let .. else expression looks like `matches!` macro",
"try",
format!(
"{}matches!({}, {pat})",
if b0 { "" } else { "!" },
snippet_with_applicability(cx, ex_new.span, "..", &mut applicability),
),
applicability,
"`if let .. else` expression looks like `matches!` macro",
|diag| {
diag.span_suggestion_verbose(
expr.span,
"use `matches!` directly",
format!(
"{}matches!({}, {pat})",
if b0 { "" } else { "!" },
snippet_with_applicability(cx, ex_new.span, "..", &mut applicability),
),
applicability,
);
},
);
}
}
Expand Down Expand Up @@ -87,7 +93,10 @@ pub(super) fn check_match<'tcx>(
// ```rs
// matches!(e, Either::Left $(if $guard)|+)
// ```
middle_arms.is_empty()
//
// But if the guard _is_ present, it may not be an `if-let` guard, as `matches!` doesn't
// support these (currently?)
(middle_arms.is_empty() && first_arm.guard.is_none_or(|g| !has_let_expr(g)))

// - (added in #6216) There are middle arms
//
Expand Down Expand Up @@ -169,18 +178,23 @@ pub(super) fn check_match<'tcx>(
{
ex_new = ex_inner;
}
span_lint_and_sugg(
span_lint_and_then(
cx,
MATCH_LIKE_MATCHES_MACRO,
e.span,
"match expression looks like `matches!` macro",
"try",
format!(
"{}matches!({}, {pat_and_guard})",
if b0 { "" } else { "!" },
snippet_with_applicability(cx, ex_new.span, "..", &mut applicability),
),
applicability,
|diag| {
diag.span_suggestion_verbose(
e.span,
"use `matches!` directly",
format!(
"{}matches!({}, {pat_and_guard})",
if b0 { "" } else { "!" },
snippet_with_applicability(cx, ex_new.span, "..", &mut applicability),
),
applicability,
);
},
);
true
} else {
Expand Down
7 changes: 7 additions & 0 deletions tests/ui/match_like_matches_macro.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -223,3 +223,10 @@ fn msrv_1_42() {
let _y = matches!(Some(5), Some(0));
//~^^^^ match_like_matches_macro
}

#[expect(clippy::option_option)]
fn issue15841(opt: Option<Option<Option<i32>>>, value: i32) {
// Lint: no if-let _in the guard_
let _ = matches!(opt, Some(first) if (if let Some(second) = first { true } else { todo!() }));
//~^^^^ match_like_matches_macro
}
10 changes: 10 additions & 0 deletions tests/ui/match_like_matches_macro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,3 +267,13 @@ fn msrv_1_42() {
};
//~^^^^ match_like_matches_macro
}

#[expect(clippy::option_option)]
fn issue15841(opt: Option<Option<Option<i32>>>, value: i32) {
// Lint: no if-let _in the guard_
let _ = match opt {
Some(first) if (if let Some(second) = first { true } else { todo!() }) => true,
_ => false,
};
//~^^^^ match_like_matches_macro
}
156 changes: 142 additions & 14 deletions tests/ui/match_like_matches_macro.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,18 @@ LL | let _y = match x {
LL | | Some(0) => true,
LL | | _ => false,
LL | | };
| |_____^ help: try: `matches!(x, Some(0))`
| |_____^
|
= note: `-D clippy::match-like-matches-macro` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::match_like_matches_macro)]`
help: use `matches!` directly
|
LL - let _y = match x {
LL - Some(0) => true,
LL - _ => false,
LL - };
LL + let _y = matches!(x, Some(0));
|

error: redundant pattern matching, consider using `is_some()`
--> tests/ui/match_like_matches_macro.rs:20:14
Expand Down Expand Up @@ -42,13 +50,28 @@ LL | let _zz = match x {
LL | | Some(r) if r == 0 => false,
LL | | _ => true,
LL | | };
| |_____^ help: try: `!matches!(x, Some(r) if r == 0)`
| |_____^
|
help: use `matches!` directly
|
LL - let _zz = match x {
LL - Some(r) if r == 0 => false,
LL - _ => true,
LL - };
LL + let _zz = !matches!(x, Some(r) if r == 0);
|

error: if let .. else expression looks like `matches!` macro
error: `if let .. else` expression looks like `matches!` macro
--> tests/ui/match_like_matches_macro.rs:41:16
|
LL | let _zzz = if let Some(5) = x { true } else { false };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `matches!(x, Some(5))`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: use `matches!` directly
|
LL - let _zzz = if let Some(5) = x { true } else { false };
LL + let _zzz = matches!(x, Some(5));
|

error: match expression looks like `matches!` macro
--> tests/ui/match_like_matches_macro.rs:66:20
Expand All @@ -59,7 +82,17 @@ LL | | E::A(_) => true,
LL | | E::B(_) => true,
LL | | _ => false,
LL | | };
| |_________^ help: try: `matches!(x, E::A(_) | E::B(_))`
| |_________^
|
help: use `matches!` directly
|
LL - let _ans = match x {
LL - E::A(_) => true,
LL - E::B(_) => true,
LL - _ => false,
LL - };
LL + let _ans = matches!(x, E::A(_) | E::B(_));
|

error: match expression looks like `matches!` macro
--> tests/ui/match_like_matches_macro.rs:77:20
Expand All @@ -71,7 +104,19 @@ LL | | true
... |
LL | | _ => false,
LL | | };
| |_________^ help: try: `matches!(x, E::A(_) | E::B(_))`
| |_________^
|
help: use `matches!` directly
|
LL - let _ans = match x {
LL - E::A(_) => {
LL - true
LL - }
LL - E::B(_) => true,
LL - _ => false,
LL - };
LL + let _ans = matches!(x, E::A(_) | E::B(_));
|

error: match expression looks like `matches!` macro
--> tests/ui/match_like_matches_macro.rs:88:20
Expand All @@ -82,7 +127,17 @@ LL | | E::B(_) => false,
LL | | E::C => false,
LL | | _ => true,
LL | | };
| |_________^ help: try: `!matches!(x, E::B(_) | E::C)`
| |_________^
|
help: use `matches!` directly
|
LL - let _ans = match x {
LL - E::B(_) => false,
LL - E::C => false,
LL - _ => true,
LL - };
LL + let _ans = !matches!(x, E::B(_) | E::C);
|

error: match expression looks like `matches!` macro
--> tests/ui/match_like_matches_macro.rs:149:18
Expand All @@ -92,7 +147,16 @@ LL | let _z = match &z {
LL | | Some(3) => true,
LL | | _ => false,
LL | | };
| |_________^ help: try: `matches!(z, Some(3))`
| |_________^
|
help: use `matches!` directly
|
LL - let _z = match &z {
LL - Some(3) => true,
LL - _ => false,
LL - };
LL + let _z = matches!(z, Some(3));
|

error: match expression looks like `matches!` macro
--> tests/ui/match_like_matches_macro.rs:159:18
Expand All @@ -102,7 +166,16 @@ LL | let _z = match &z {
LL | | Some(3) => true,
LL | | _ => false,
LL | | };
| |_________^ help: try: `matches!(&z, Some(3))`
| |_________^
|
help: use `matches!` directly
|
LL - let _z = match &z {
LL - Some(3) => true,
LL - _ => false,
LL - };
LL + let _z = matches!(&z, Some(3));
|

error: match expression looks like `matches!` macro
--> tests/ui/match_like_matches_macro.rs:177:21
Expand All @@ -112,7 +185,16 @@ LL | let _ = match &z {
LL | | AnEnum::X => true,
LL | | _ => false,
LL | | };
| |_____________^ help: try: `matches!(&z, AnEnum::X)`
| |_____________^
|
help: use `matches!` directly
|
LL - let _ = match &z {
LL - AnEnum::X => true,
LL - _ => false,
LL - };
LL + let _ = matches!(&z, AnEnum::X);
|

error: match expression looks like `matches!` macro
--> tests/ui/match_like_matches_macro.rs:192:20
Expand All @@ -122,7 +204,16 @@ LL | let _res = match &val {
LL | | &Some(ref _a) => true,
LL | | _ => false,
LL | | };
| |_________^ help: try: `matches!(&val, &Some(ref _a))`
| |_________^
|
help: use `matches!` directly
|
LL - let _res = match &val {
LL - &Some(ref _a) => true,
LL - _ => false,
LL - };
LL + let _res = matches!(&val, &Some(ref _a));
|

error: match expression looks like `matches!` macro
--> tests/ui/match_like_matches_macro.rs:205:20
Expand All @@ -132,7 +223,16 @@ LL | let _res = match &val {
LL | | &Some(ref _a) => true,
LL | | _ => false,
LL | | };
| |_________^ help: try: `matches!(&val, &Some(ref _a))`
| |_________^
|
help: use `matches!` directly
|
LL - let _res = match &val {
LL - &Some(ref _a) => true,
LL - _ => false,
LL - };
LL + let _res = matches!(&val, &Some(ref _a));
|

error: match expression looks like `matches!` macro
--> tests/ui/match_like_matches_macro.rs:264:14
Expand All @@ -142,7 +242,35 @@ LL | let _y = match Some(5) {
LL | | Some(0) => true,
LL | | _ => false,
LL | | };
| |_____^ help: try: `matches!(Some(5), Some(0))`
| |_____^
|
help: use `matches!` directly
|
LL - let _y = match Some(5) {
LL - Some(0) => true,
LL - _ => false,
LL - };
LL + let _y = matches!(Some(5), Some(0));
|

error: match expression looks like `matches!` macro
--> tests/ui/match_like_matches_macro.rs:274:13
|
LL | let _ = match opt {
| _____________^
LL | | Some(first) if (if let Some(second) = first { true } else { todo!() }) => true,
LL | | _ => false,
LL | | };
| |_____^
|
help: use `matches!` directly
|
LL - let _ = match opt {
LL - Some(first) if (if let Some(second) = first { true } else { todo!() }) => true,
LL - _ => false,
LL - };
LL + let _ = matches!(opt, Some(first) if (if let Some(second) = first { true } else { todo!() }));
|

error: aborting due to 14 previous errors
error: aborting due to 15 previous errors

Loading