Skip to content

Commit 85e2592

Browse files
committed
Auto merge of #7909 - mikerite:fix-7816, r=camsteffen
Fix false negative in [`match_overlapping_arms`] changelog: Fix false negative in [`match_overlapping_arms`]
2 parents 84a4ab7 + 693df63 commit 85e2592

File tree

3 files changed

+72
-25
lines changed

3 files changed

+72
-25
lines changed

clippy_lints/src/matches.rs

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ use rustc_span::source_map::{Span, Spanned};
3434
use rustc_span::sym;
3535
use std::cmp::Ordering;
3636
use std::collections::hash_map::Entry;
37-
use std::iter;
3837
use std::ops::Bound;
3938

4039
declare_clippy_lint! {
@@ -1707,12 +1706,6 @@ where
17071706
}
17081707

17091708
impl<'a, T: Copy> Kind<'a, T> {
1710-
fn range(&self) -> &'a SpannedRange<T> {
1711-
match *self {
1712-
Kind::Start(_, r) | Kind::End(_, r) => r,
1713-
}
1714-
}
1715-
17161709
fn value(self) -> Bound<T> {
17171710
match self {
17181711
Kind::Start(t, _) => Bound::Included(t),
@@ -1730,7 +1723,19 @@ where
17301723
impl<'a, T: Copy + Ord> Ord for Kind<'a, T> {
17311724
fn cmp(&self, other: &Self) -> Ordering {
17321725
match (self.value(), other.value()) {
1733-
(Bound::Included(a), Bound::Included(b)) | (Bound::Excluded(a), Bound::Excluded(b)) => a.cmp(&b),
1726+
(Bound::Included(a), Bound::Included(b)) | (Bound::Excluded(a), Bound::Excluded(b)) => {
1727+
let value_cmp = a.cmp(&b);
1728+
// In the case of ties, starts come before ends
1729+
if value_cmp == Ordering::Equal {
1730+
match (self, other) {
1731+
(Kind::Start(..), Kind::End(..)) => Ordering::Less,
1732+
(Kind::End(..), Kind::Start(..)) => Ordering::Greater,
1733+
_ => Ordering::Equal,
1734+
}
1735+
} else {
1736+
value_cmp
1737+
}
1738+
},
17341739
// Range patterns cannot be unbounded (yet)
17351740
(Bound::Unbounded, _) | (_, Bound::Unbounded) => unimplemented!(),
17361741
(Bound::Included(a), Bound::Excluded(b)) => match a.cmp(&b) {
@@ -1754,24 +1759,24 @@ where
17541759

17551760
values.sort();
17561761

1757-
for (a, b) in iter::zip(&values, values.iter().skip(1)) {
1758-
match (a, b) {
1759-
(&Kind::Start(_, ra), &Kind::End(_, rb)) => {
1760-
if ra.node != rb.node {
1761-
return Some((ra, rb));
1762-
}
1763-
},
1764-
(&Kind::End(a, _), &Kind::Start(b, _)) if a != Bound::Included(b) => (),
1765-
_ => {
1766-
// skip if the range `a` is completely included into the range `b`
1767-
if let Ordering::Equal | Ordering::Less = a.cmp(b) {
1768-
let kind_a = Kind::End(a.range().node.1, a.range());
1769-
let kind_b = Kind::End(b.range().node.1, b.range());
1770-
if let Ordering::Equal | Ordering::Greater = kind_a.cmp(&kind_b) {
1771-
return None;
1762+
let mut started = vec![];
1763+
1764+
for value in values {
1765+
match value {
1766+
Kind::Start(_, r) => started.push(r),
1767+
Kind::End(_, er) => {
1768+
let mut overlap = None;
1769+
1770+
while let Some(sr) = started.pop() {
1771+
if sr == er {
1772+
break;
17721773
}
1774+
overlap = Some(sr);
1775+
}
1776+
1777+
if let Some(sr) = overlap {
1778+
return Some((er, sr));
17731779
}
1774-
return Some((a.range(), b.range()));
17751780
},
17761781
}
17771782
}

tests/ui/match_overlapping_arm.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,31 @@ fn overlapping() {
100100
_ => (),
101101
}
102102

103+
// Issue #7816 - overlap after included range
104+
match 42 {
105+
5..=10 => (),
106+
0..=20 => (),
107+
21..=30 => (),
108+
21..=40 => (),
109+
_ => (),
110+
}
111+
103112
// Issue #7829
104113
match 0 {
105114
-1..=1 => (),
106115
-2..=2 => (),
107116
_ => (),
108117
}
109118

119+
// Only warn about the first if there are multiple overlaps
120+
match 42u128 {
121+
0..=0x0000_0000_0000_00ff => (),
122+
0..=0x0000_0000_0000_ffff => (),
123+
0..=0x0000_0000_ffff_ffff => (),
124+
0..=0xffff_ffff_ffff_ffff => (),
125+
_ => (),
126+
}
127+
110128
if let None = Some(42) {
111129
// nothing
112130
} else if let None = Some(42) {

tests/ui/match_overlapping_arm.stderr

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,5 +71,29 @@ note: overlaps with this
7171
LL | ..26 => println!("..26"),
7272
| ^^^^
7373

74-
error: aborting due to 6 previous errors
74+
error: some ranges overlap
75+
--> $DIR/match_overlapping_arm.rs:107:9
76+
|
77+
LL | 21..=30 => (),
78+
| ^^^^^^^
79+
|
80+
note: overlaps with this
81+
--> $DIR/match_overlapping_arm.rs:108:9
82+
|
83+
LL | 21..=40 => (),
84+
| ^^^^^^^
85+
86+
error: some ranges overlap
87+
--> $DIR/match_overlapping_arm.rs:121:9
88+
|
89+
LL | 0..=0x0000_0000_0000_00ff => (),
90+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
91+
|
92+
note: overlaps with this
93+
--> $DIR/match_overlapping_arm.rs:122:9
94+
|
95+
LL | 0..=0x0000_0000_0000_ffff => (),
96+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
97+
98+
error: aborting due to 8 previous errors
7599

0 commit comments

Comments
 (0)