Skip to content

Commit 93f13d5

Browse files
committed
Auto merge of rust-lang#7951 - mikerite:matches-20211109, r=llogiq
`match_overlapping_arm` refactoring The main purpose of this pull request is to remove the unneeded and scary `unimplented!()` in the `match_arm_overlapping` code. The rest is gratuitous refactoring. changelog: none
2 parents f69721f + 8b76915 commit 93f13d5

File tree

1 file changed

+55
-75
lines changed

1 file changed

+55
-75
lines changed

clippy_lints/src/matches.rs

+55-75
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ use rustc_span::source_map::{Span, Spanned};
3333
use rustc_span::sym;
3434
use std::cmp::Ordering;
3535
use std::collections::hash_map::Entry;
36-
use std::ops::Bound;
3736

3837
declare_clippy_lint! {
3938
/// ### What it does
@@ -1596,27 +1595,27 @@ fn opt_parent_let<'a>(cx: &LateContext<'a>, ex: &Expr<'a>) -> Option<&'a Local<'
15961595
None
15971596
}
15981597

1599-
/// Gets all arms that are unbounded `PatRange`s.
1598+
/// Gets the ranges for each range pattern arm. Applies `ty` bounds for open ranges.
16001599
fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>) -> Vec<SpannedRange<FullInt>> {
16011600
arms.iter()
16021601
.filter_map(|arm| {
16031602
if let Arm { pat, guard: None, .. } = *arm {
16041603
if let PatKind::Range(ref lhs, ref rhs, range_end) = pat.kind {
1605-
let lhs = match lhs {
1604+
let lhs_const = match lhs {
16061605
Some(lhs) => constant(cx, cx.typeck_results(), lhs)?.0,
16071606
None => miri_to_const(ty.numeric_min_val(cx.tcx)?)?,
16081607
};
1609-
let rhs = match rhs {
1608+
let rhs_const = match rhs {
16101609
Some(rhs) => constant(cx, cx.typeck_results(), rhs)?.0,
16111610
None => miri_to_const(ty.numeric_max_val(cx.tcx)?)?,
16121611
};
16131612

1614-
let lhs_val = lhs.int_value(cx, ty)?;
1615-
let rhs_val = rhs.int_value(cx, ty)?;
1613+
let lhs_val = lhs_const.int_value(cx, ty)?;
1614+
let rhs_val = rhs_const.int_value(cx, ty)?;
16161615

16171616
let rhs_bound = match range_end {
1618-
RangeEnd::Included => Bound::Included(rhs_val),
1619-
RangeEnd::Excluded => Bound::Excluded(rhs_val),
1617+
RangeEnd::Included => EndBound::Included(rhs_val),
1618+
RangeEnd::Excluded => EndBound::Excluded(rhs_val),
16201619
};
16211620
return Some(SpannedRange {
16221621
span: pat.span,
@@ -1628,7 +1627,7 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
16281627
let value = constant_full_int(cx, cx.typeck_results(), value)?;
16291628
return Some(SpannedRange {
16301629
span: pat.span,
1631-
node: (value, Bound::Included(value)),
1630+
node: (value, EndBound::Included(value)),
16321631
});
16331632
}
16341633
}
@@ -1637,10 +1636,16 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
16371636
.collect()
16381637
}
16391638

1639+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1640+
pub enum EndBound<T> {
1641+
Included(T),
1642+
Excluded(T),
1643+
}
1644+
16401645
#[derive(Debug, Eq, PartialEq)]
1641-
pub struct SpannedRange<T> {
1646+
struct SpannedRange<T> {
16421647
pub span: Span,
1643-
pub node: (T, Bound<T>),
1648+
pub node: (T, EndBound<T>),
16441649
}
16451650

16461651
// Checks if arm has the form `None => None`
@@ -1689,87 +1694,62 @@ where
16891694
ref_count > 1
16901695
}
16911696

1692-
pub fn overlapping<T>(ranges: &[SpannedRange<T>]) -> Option<(&SpannedRange<T>, &SpannedRange<T>)>
1697+
fn overlapping<T>(ranges: &[SpannedRange<T>]) -> Option<(&SpannedRange<T>, &SpannedRange<T>)>
16931698
where
16941699
T: Copy + Ord,
16951700
{
1696-
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
1697-
enum Kind<'a, T> {
1698-
Start(T, &'a SpannedRange<T>),
1699-
End(Bound<T>, &'a SpannedRange<T>),
1701+
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
1702+
enum BoundKind {
1703+
EndExcluded,
1704+
Start,
1705+
EndIncluded,
17001706
}
17011707

1702-
impl<'a, T: Copy> Kind<'a, T> {
1703-
fn value(self) -> Bound<T> {
1704-
match self {
1705-
Kind::Start(t, _) => Bound::Included(t),
1706-
Kind::End(t, _) => t,
1707-
}
1708-
}
1709-
}
1708+
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
1709+
struct RangeBound<'a, T>(T, BoundKind, &'a SpannedRange<T>);
17101710

1711-
impl<'a, T: Copy + Ord> PartialOrd for Kind<'a, T> {
1711+
impl<'a, T: Copy + Ord> PartialOrd for RangeBound<'a, T> {
17121712
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
17131713
Some(self.cmp(other))
17141714
}
17151715
}
17161716

1717-
impl<'a, T: Copy + Ord> Ord for Kind<'a, T> {
1718-
fn cmp(&self, other: &Self) -> Ordering {
1719-
match (self.value(), other.value()) {
1720-
(Bound::Included(a), Bound::Included(b)) | (Bound::Excluded(a), Bound::Excluded(b)) => {
1721-
let value_cmp = a.cmp(&b);
1722-
// In the case of ties, starts come before ends
1723-
if value_cmp == Ordering::Equal {
1724-
match (self, other) {
1725-
(Kind::Start(..), Kind::End(..)) => Ordering::Less,
1726-
(Kind::End(..), Kind::Start(..)) => Ordering::Greater,
1727-
_ => Ordering::Equal,
1728-
}
1729-
} else {
1730-
value_cmp
1731-
}
1732-
},
1733-
// Range patterns cannot be unbounded (yet)
1734-
(Bound::Unbounded, _) | (_, Bound::Unbounded) => unimplemented!(),
1735-
(Bound::Included(a), Bound::Excluded(b)) => match a.cmp(&b) {
1736-
Ordering::Equal => Ordering::Greater,
1737-
other => other,
1738-
},
1739-
(Bound::Excluded(a), Bound::Included(b)) => match a.cmp(&b) {
1740-
Ordering::Equal => Ordering::Less,
1741-
other => other,
1742-
},
1743-
}
1717+
impl<'a, T: Copy + Ord> Ord for RangeBound<'a, T> {
1718+
fn cmp(&self, RangeBound(other_value, other_kind, _): &Self) -> Ordering {
1719+
let RangeBound(self_value, self_kind, _) = *self;
1720+
(self_value, self_kind).cmp(&(*other_value, *other_kind))
17441721
}
17451722
}
17461723

17471724
let mut values = Vec::with_capacity(2 * ranges.len());
17481725

1749-
for r in ranges {
1750-
values.push(Kind::Start(r.node.0, r));
1751-
values.push(Kind::End(r.node.1, r));
1726+
for r @ SpannedRange { node: (start, end), .. } in ranges {
1727+
values.push(RangeBound(*start, BoundKind::Start, r));
1728+
values.push(match end {
1729+
EndBound::Excluded(val) => RangeBound(*val, BoundKind::EndExcluded, r),
1730+
EndBound::Included(val) => RangeBound(*val, BoundKind::EndIncluded, r),
1731+
});
17521732
}
17531733

17541734
values.sort();
17551735

17561736
let mut started = vec![];
17571737

1758-
for value in values {
1759-
match value {
1760-
Kind::Start(_, r) => started.push(r),
1761-
Kind::End(_, er) => {
1738+
for RangeBound(_, kind, range) in values {
1739+
match kind {
1740+
BoundKind::Start => started.push(range),
1741+
BoundKind::EndExcluded | BoundKind::EndIncluded => {
17621742
let mut overlap = None;
17631743

1764-
while let Some(sr) = started.pop() {
1765-
if sr == er {
1744+
while let Some(last_started) = started.pop() {
1745+
if last_started == range {
17661746
break;
17671747
}
1768-
overlap = Some(sr);
1748+
overlap = Some(last_started);
17691749
}
17701750

1771-
if let Some(sr) = overlap {
1772-
return Some((er, sr));
1751+
if let Some(first_overlapping) = overlap {
1752+
return Some((range, first_overlapping));
17731753
}
17741754
},
17751755
}
@@ -2227,29 +2207,29 @@ fn test_overlapping() {
22272207
};
22282208

22292209
assert_eq!(None, overlapping::<u8>(&[]));
2230-
assert_eq!(None, overlapping(&[sp(1, Bound::Included(4))]));
2210+
assert_eq!(None, overlapping(&[sp(1, EndBound::Included(4))]));
22312211
assert_eq!(
22322212
None,
2233-
overlapping(&[sp(1, Bound::Included(4)), sp(5, Bound::Included(6))])
2213+
overlapping(&[sp(1, EndBound::Included(4)), sp(5, EndBound::Included(6))])
22342214
);
22352215
assert_eq!(
22362216
None,
22372217
overlapping(&[
2238-
sp(1, Bound::Included(4)),
2239-
sp(5, Bound::Included(6)),
2240-
sp(10, Bound::Included(11))
2218+
sp(1, EndBound::Included(4)),
2219+
sp(5, EndBound::Included(6)),
2220+
sp(10, EndBound::Included(11))
22412221
],)
22422222
);
22432223
assert_eq!(
2244-
Some((&sp(1, Bound::Included(4)), &sp(3, Bound::Included(6)))),
2245-
overlapping(&[sp(1, Bound::Included(4)), sp(3, Bound::Included(6))])
2224+
Some((&sp(1, EndBound::Included(4)), &sp(3, EndBound::Included(6)))),
2225+
overlapping(&[sp(1, EndBound::Included(4)), sp(3, EndBound::Included(6))])
22462226
);
22472227
assert_eq!(
2248-
Some((&sp(5, Bound::Included(6)), &sp(6, Bound::Included(11)))),
2228+
Some((&sp(5, EndBound::Included(6)), &sp(6, EndBound::Included(11)))),
22492229
overlapping(&[
2250-
sp(1, Bound::Included(4)),
2251-
sp(5, Bound::Included(6)),
2252-
sp(6, Bound::Included(11))
2230+
sp(1, EndBound::Included(4)),
2231+
sp(5, EndBound::Included(6)),
2232+
sp(6, EndBound::Included(11))
22532233
],)
22542234
);
22552235
}

0 commit comments

Comments
 (0)