@@ -21,27 +21,30 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) {
21
21
};
22
22
23
23
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();
25
28
26
29
// 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
28
31
.iter()
29
32
.enumerate()
30
33
.map(|(i, pat)| {
31
- resolved_pats [i + 1..]
34
+ normalized_pats [i + 1..]
32
35
.iter()
33
36
.enumerate()
34
37
.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())
36
39
})
37
40
.collect();
38
41
39
42
// 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
41
44
.iter()
42
45
.enumerate()
43
46
.map(|(i, pat)| {
44
- resolved_pats [..i]
47
+ normalized_pats [..i]
45
48
.iter()
46
49
.enumerate()
47
50
.rev()
@@ -133,18 +136,18 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) {
133
136
}
134
137
135
138
#[derive(Clone, Copy)]
136
- enum ResolvedPat<'hir, 'arena > {
139
+ enum NormalizedPat<'a > {
137
140
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]),
141
144
Path(Option<DefId>),
142
145
LitStr(Symbol),
143
- LitBytes(&'hir [u8]),
146
+ LitBytes(&'a [u8]),
144
147
LitInt(u128),
145
148
LitBool(bool),
146
149
Range(PatRange),
147
- Slice(&'arena [Self], &'arena [Self], bool ),
150
+ Slice(&'a [Self], Option<&'a [Self]> ),
148
151
}
149
152
150
153
#[derive(Clone, Copy)]
@@ -183,9 +186,9 @@ impl PatRange {
183
186
}
184
187
185
188
#[allow(clippy::similar_names)]
186
- impl<'hir, 'arena> ResolvedPat<'hir, 'arena > {
189
+ impl<'a> NormalizedPat<'a > {
187
190
#[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 {
189
192
match pat.kind {
190
193
PatKind::Wild | PatKind::Binding(.., None) => Self::Wild,
191
194
PatKind::Binding(.., Some(pat)) | PatKind::Box(pat) | PatKind::Ref(pat, _) => {
@@ -284,8 +287,7 @@ impl<'hir, 'arena> ResolvedPat<'hir, 'arena> {
284
287
},
285
288
PatKind::Slice(front, wild_pat, back) => Self::Slice(
286
289
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)))),
289
291
),
290
292
}
291
293
}
@@ -345,6 +347,25 @@ impl<'hir, 'arena> ResolvedPat<'hir, 'arena> {
345
347
(Self::LitBool(x), Self::LitBool(y)) => x == y,
346
348
(Self::Range(ref x), Self::Range(ref y)) => x.overlaps(y),
347
349
(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)),
348
369
349
370
// Todo: Lit* with Path, Range with Path, LitBytes with Slice, Slice with Slice
350
371
_ => true,
0 commit comments