Skip to content

Commit 0535908

Browse files
committed
final refactor and docs
1 parent dd7f605 commit 0535908

File tree

1 file changed

+59
-5
lines changed

1 file changed

+59
-5
lines changed

clippy_lints/src/matches/match_like_matches.rs

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,65 @@ pub(super) fn check_match<'tcx>(
7272
&& let Some(b0) = find_bool_lit(first_arm.body)
7373
&& let Some(b1) = find_bool_lit(last_arm.body)
7474
&& b0 != b1
75-
&& (first_arm.guard.is_none() || middle_arms.is_empty())
76-
&& cx.tcx.hir_attrs(first_arm.hir_id).is_empty()
77-
&& middle_arms.iter().all(|arm| {
78-
cx.tcx.hir_attrs(arm.hir_id).is_empty() && arm.guard.is_none() && find_bool_lit(arm.body) == Some(b0)
79-
})
75+
// We handle two cases:
76+
&& (
77+
// - There are no middle arms, i.e., 2 arms in total
78+
//
79+
// In that case, the first arm may or may not have a guard, because this:
80+
// ```rs
81+
// match e {
82+
// Either::Left $(if $guard)|+ => true, // or `false`, but then we'll need `!matches!(..)`
83+
// _ => false,
84+
// }
85+
// ```
86+
// can always become this:
87+
// ```rs
88+
// matches!(e, Either::Left $(if $guard)|+)
89+
// ```
90+
middle_arms.is_empty()
91+
92+
// - (added in #6216) There are middle arms
93+
//
94+
// In that case, neither they nor the first arm may have guards
95+
// -- otherwise, they couldn't be combined into an or-pattern in `matches!`
96+
//
97+
// This:
98+
// ```rs
99+
// match e {
100+
// Either3::First => true,
101+
// Either3::Second => true,
102+
// _ /* matches `Either3::Third` */ => false,
103+
// }
104+
// ```
105+
// can become this:
106+
// ```rs
107+
// matches!(e, Either3::First | Either3::Second)
108+
// ```
109+
//
110+
// But this:
111+
// ```rs
112+
// match e {
113+
// Either3::First if X => true,
114+
// Either3::Second => true,
115+
// _ => false,
116+
// }
117+
// ```
118+
// cannot be transformed.
119+
//
120+
// We set an additional constraint of all of them needing to return the same bool,
121+
// so we don't lint things like:
122+
// ```rs
123+
// match e {
124+
// Either3::First => true,
125+
// Either3::Second => false,
126+
// _ => false,
127+
// }
128+
// ```
129+
// This is not *strictly* necessary, but it simplifies the logic a bit
130+
|| arms_without_last.iter().all(|arm| {
131+
cx.tcx.hir_attrs(arm.hir_id).is_empty() && arm.guard.is_none() && find_bool_lit(arm.body) == Some(b0)
132+
})
133+
)
80134
{
81135
if !is_wild(last_arm.pat) {
82136
return false;

0 commit comments

Comments
 (0)