Skip to content

Commit 11b1fc7

Browse files
committed
Handle slice patterns in match_same_arms
1 parent 465faae commit 11b1fc7

File tree

1 file changed

+37
-16
lines changed

1 file changed

+37
-16
lines changed

clippy_lints/src/matches.rs

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2245,18 +2245,18 @@ fn test_overlapping() {
22452245
}
22462246

22472247
#[derive(Clone, Copy)]
2248-
enum ResolvedPat<'hir, 'arena> {
2248+
enum NormalizedPat<'a> {
22492249
Wild,
2250-
Struct(Option<DefId>, &'arena [(Symbol, Self)]),
2251-
Tuple(Option<DefId>, &'arena [Self]),
2252-
Or(&'arena [Self]),
2250+
Struct(Option<DefId>, &'a [(Symbol, Self)]),
2251+
Tuple(Option<DefId>, &'a [Self]),
2252+
Or(&'a [Self]),
22532253
Path(Option<DefId>),
22542254
LitStr(Symbol),
2255-
LitBytes(&'hir [u8]),
2255+
LitBytes(&'a [u8]),
22562256
LitInt(u128),
22572257
LitBool(bool),
22582258
Range(PatRange),
2259-
Slice(&'arena [Self], &'arena [Self], bool),
2259+
Slice(&'a [Self], Option<&'a [Self]>),
22602260
}
22612261

22622262
#[derive(Clone, Copy)]
@@ -2295,9 +2295,9 @@ impl PatRange {
22952295
}
22962296

22972297
#[allow(clippy::similar_names)]
2298-
impl<'hir, 'arena> ResolvedPat<'hir, 'arena> {
2298+
impl<'a> NormalizedPat<'a> {
22992299
#[allow(clippy::too_many_lines)]
2300-
fn from_pat(cx: &LateContext<'_>, arena: &'arena DroplessArena, pat: &'hir Pat<'_>) -> Self {
2300+
fn from_pat(cx: &LateContext<'_>, arena: &'a DroplessArena, pat: &'a Pat<'_>) -> Self {
23012301
match pat.kind {
23022302
PatKind::Wild | PatKind::Binding(.., None) => Self::Wild,
23032303
PatKind::Binding(.., Some(pat)) | PatKind::Box(pat) | PatKind::Ref(pat, _) => {
@@ -2396,8 +2396,7 @@ impl<'hir, 'arena> ResolvedPat<'hir, 'arena> {
23962396
},
23972397
PatKind::Slice(front, wild_pat, back) => Self::Slice(
23982398
arena.alloc_from_iter(front.iter().map(|pat| Self::from_pat(cx, arena, pat))),
2399-
arena.alloc_from_iter(back.iter().map(|pat| Self::from_pat(cx, arena, pat))),
2400-
wild_pat.is_some(),
2399+
wild_pat.map(|_| &*arena.alloc_from_iter(back.iter().map(|pat| Self::from_pat(cx, arena, pat)))),
24012400
),
24022401
}
24032402
}
@@ -2457,6 +2456,25 @@ impl<'hir, 'arena> ResolvedPat<'hir, 'arena> {
24572456
(Self::LitBool(x), Self::LitBool(y)) => x == y,
24582457
(Self::Range(ref x), Self::Range(ref y)) => x.overlaps(y),
24592458
(Self::Range(ref range), Self::LitInt(x)) | (Self::LitInt(x), Self::Range(ref range)) => range.contains(x),
2459+
(Self::Slice(lpats, None), Self::Slice(rpats, None)) => {
2460+
lpats.len() == rpats.len() && lpats.iter().zip(rpats.iter()).all(|(x, y)| x.can_also_match(y))
2461+
},
2462+
(Self::Slice(pats, None), Self::Slice(front, Some(back)))
2463+
| (Self::Slice(front, Some(back)), Self::Slice(pats, None)) => {
2464+
if pats.len() < front.len() + back.len() {
2465+
return false;
2466+
}
2467+
pats[..front.len()]
2468+
.iter()
2469+
.zip(front.iter())
2470+
.chain(pats[pats.len() - back.len()..].iter().zip(back.iter()))
2471+
.all(|(x, y)| x.can_also_match(y))
2472+
},
2473+
(Self::Slice(lfront, Some(lback)), Self::Slice(rfront, Some(rback))) => lfront
2474+
.iter()
2475+
.zip(rfront.iter())
2476+
.chain(lback.iter().rev().zip(rback.iter().rev()))
2477+
.all(|(x, y)| x.can_also_match(y)),
24602478

24612479
// Todo: Lit* with Path, Range with Path, LitBytes with Slice, Slice with Slice
24622480
_ => true,
@@ -2474,27 +2492,30 @@ fn lint_match_arms<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>) {
24742492
};
24752493

24762494
let arena = DroplessArena::default();
2477-
let resolved_pats: Vec<_> = arms.iter().map(|a| ResolvedPat::from_pat(cx, &arena, a.pat)).collect();
2495+
let normalized_pats: Vec<_> = arms
2496+
.iter()
2497+
.map(|a| NormalizedPat::from_pat(cx, &arena, a.pat))
2498+
.collect();
24782499

24792500
// The furthast forwards a pattern can move without semantic changes
2480-
let forwards_blocking_idxs: Vec<_> = resolved_pats
2501+
let forwards_blocking_idxs: Vec<_> = normalized_pats
24812502
.iter()
24822503
.enumerate()
24832504
.map(|(i, pat)| {
2484-
resolved_pats[i + 1..]
2505+
normalized_pats[i + 1..]
24852506
.iter()
24862507
.enumerate()
24872508
.find_map(|(j, other)| pat.can_also_match(other).then(|| i + 1 + j))
2488-
.unwrap_or(resolved_pats.len())
2509+
.unwrap_or(normalized_pats.len())
24892510
})
24902511
.collect();
24912512

24922513
// The furthast backwards a pattern can move without semantic changes
2493-
let backwards_blocking_idxs: Vec<_> = resolved_pats
2514+
let backwards_blocking_idxs: Vec<_> = normalized_pats
24942515
.iter()
24952516
.enumerate()
24962517
.map(|(i, pat)| {
2497-
resolved_pats[..i]
2518+
normalized_pats[..i]
24982519
.iter()
24992520
.enumerate()
25002521
.rev()

0 commit comments

Comments
 (0)