Skip to content

Commit 4f8f4b4

Browse files
committed
Handle slice patterns in match_same_arms
1 parent 5508f46 commit 4f8f4b4

File tree

1 file changed

+37
-16
lines changed

1 file changed

+37
-16
lines changed

clippy_lints/src/matches/match_same_arms.rs

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,27 +21,30 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) {
2121
};
2222

2323
let arena = DroplessArena::default();
24-
let resolved_pats: Vec<_> = arms.iter().map(|a| ResolvedPat::from_pat(cx, &arena, a.pat)).collect();
24+
let normalized_pats: Vec<_> = arms
25+
.iter()
26+
.map(|a| NormalizedPat::from_pat(cx, &arena, a.pat))
27+
.collect();
2528

2629
// The furthast forwards a pattern can move without semantic changes
27-
let forwards_blocking_idxs: Vec<_> = resolved_pats
30+
let forwards_blocking_idxs: Vec<_> = normalized_pats
2831
.iter()
2932
.enumerate()
3033
.map(|(i, pat)| {
31-
resolved_pats[i + 1..]
34+
normalized_pats[i + 1..]
3235
.iter()
3336
.enumerate()
3437
.find_map(|(j, other)| pat.can_also_match(other).then(|| i + 1 + j))
35-
.unwrap_or(resolved_pats.len())
38+
.unwrap_or(normalized_pats.len())
3639
})
3740
.collect();
3841

3942
// The furthast backwards a pattern can move without semantic changes
40-
let backwards_blocking_idxs: Vec<_> = resolved_pats
43+
let backwards_blocking_idxs: Vec<_> = normalized_pats
4144
.iter()
4245
.enumerate()
4346
.map(|(i, pat)| {
44-
resolved_pats[..i]
47+
normalized_pats[..i]
4548
.iter()
4649
.enumerate()
4750
.rev()
@@ -133,18 +136,18 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) {
133136
}
134137

135138
#[derive(Clone, Copy)]
136-
enum ResolvedPat<'hir, 'arena> {
139+
enum NormalizedPat<'a> {
137140
Wild,
138-
Struct(Option<DefId>, &'arena [(Symbol, Self)]),
139-
Tuple(Option<DefId>, &'arena [Self]),
140-
Or(&'arena [Self]),
141+
Struct(Option<DefId>, &'a [(Symbol, Self)]),
142+
Tuple(Option<DefId>, &'a [Self]),
143+
Or(&'a [Self]),
141144
Path(Option<DefId>),
142145
LitStr(Symbol),
143-
LitBytes(&'hir [u8]),
146+
LitBytes(&'a [u8]),
144147
LitInt(u128),
145148
LitBool(bool),
146149
Range(PatRange),
147-
Slice(&'arena [Self], &'arena [Self], bool),
150+
Slice(&'a [Self], Option<&'a [Self]>),
148151
}
149152

150153
#[derive(Clone, Copy)]
@@ -183,9 +186,9 @@ impl PatRange {
183186
}
184187

185188
#[allow(clippy::similar_names)]
186-
impl<'hir, 'arena> ResolvedPat<'hir, 'arena> {
189+
impl<'a> NormalizedPat<'a> {
187190
#[allow(clippy::too_many_lines)]
188-
fn from_pat(cx: &LateContext<'_>, arena: &'arena DroplessArena, pat: &'hir Pat<'_>) -> Self {
191+
fn from_pat(cx: &LateContext<'_>, arena: &'a DroplessArena, pat: &'a Pat<'_>) -> Self {
189192
match pat.kind {
190193
PatKind::Wild | PatKind::Binding(.., None) => Self::Wild,
191194
PatKind::Binding(.., Some(pat)) | PatKind::Box(pat) | PatKind::Ref(pat, _) => {
@@ -284,8 +287,7 @@ impl<'hir, 'arena> ResolvedPat<'hir, 'arena> {
284287
},
285288
PatKind::Slice(front, wild_pat, back) => Self::Slice(
286289
arena.alloc_from_iter(front.iter().map(|pat| Self::from_pat(cx, arena, pat))),
287-
arena.alloc_from_iter(back.iter().map(|pat| Self::from_pat(cx, arena, pat))),
288-
wild_pat.is_some(),
290+
wild_pat.map(|_| &*arena.alloc_from_iter(back.iter().map(|pat| Self::from_pat(cx, arena, pat)))),
289291
),
290292
}
291293
}
@@ -345,6 +347,25 @@ impl<'hir, 'arena> ResolvedPat<'hir, 'arena> {
345347
(Self::LitBool(x), Self::LitBool(y)) => x == y,
346348
(Self::Range(ref x), Self::Range(ref y)) => x.overlaps(y),
347349
(Self::Range(ref range), Self::LitInt(x)) | (Self::LitInt(x), Self::Range(ref range)) => range.contains(x),
350+
(Self::Slice(lpats, None), Self::Slice(rpats, None)) => {
351+
lpats.len() == rpats.len() && lpats.iter().zip(rpats.iter()).all(|(x, y)| x.can_also_match(y))
352+
},
353+
(Self::Slice(pats, None), Self::Slice(front, Some(back)))
354+
| (Self::Slice(front, Some(back)), Self::Slice(pats, None)) => {
355+
if pats.len() < front.len() + back.len() {
356+
return false;
357+
}
358+
pats[..front.len()]
359+
.iter()
360+
.zip(front.iter())
361+
.chain(pats[pats.len() - back.len()..].iter().zip(back.iter()))
362+
.all(|(x, y)| x.can_also_match(y))
363+
},
364+
(Self::Slice(lfront, Some(lback)), Self::Slice(rfront, Some(rback))) => lfront
365+
.iter()
366+
.zip(rfront.iter())
367+
.chain(lback.iter().rev().zip(rback.iter().rev()))
368+
.all(|(x, y)| x.can_also_match(y)),
348369

349370
// Todo: Lit* with Path, Range with Path, LitBytes with Slice, Slice with Slice
350371
_ => true,

0 commit comments

Comments
 (0)