Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit d898365

Browse files
committed
Correctly detect usize/isize range overlaps
1 parent 4ae328b commit d898365

File tree

3 files changed

+20
-31
lines changed

3 files changed

+20
-31
lines changed

compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs

Lines changed: 12 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,6 @@ impl<'tcx> IntRange<'tcx> {
5858
(*self.range.start(), *self.range.end())
5959
}
6060

61-
/// Don't treat `usize`/`isize` exhaustively unless the `precise_pointer_size_matching` feature
62-
/// is enabled.
63-
fn treat_exhaustively(&self, tcx: TyCtxt<'tcx>) -> bool {
64-
!self.ty.is_ptr_sized_integral() || tcx.features().precise_pointer_size_matching
65-
}
66-
6761
#[inline]
6862
fn integral_size_and_signed_bias(tcx: TyCtxt<'tcx>, ty: Ty<'_>) -> Option<(Size, u128)> {
6963
match *ty.kind() {
@@ -147,20 +141,15 @@ impl<'tcx> IntRange<'tcx> {
147141
other.range.start() <= self.range.start() && self.range.end() <= other.range.end()
148142
}
149143

150-
fn intersection(&self, tcx: TyCtxt<'tcx>, other: &Self) -> Option<Self> {
144+
fn intersection(&self, other: &Self) -> Option<Self> {
151145
let ty = self.ty;
152146
let (lo, hi) = self.boundaries();
153147
let (other_lo, other_hi) = other.boundaries();
154-
if self.treat_exhaustively(tcx) {
155-
if lo <= other_hi && other_lo <= hi {
156-
let span = other.span;
157-
Some(IntRange { range: max(lo, other_lo)..=min(hi, other_hi), ty, span })
158-
} else {
159-
None
160-
}
148+
if lo <= other_hi && other_lo <= hi {
149+
let span = other.span;
150+
Some(IntRange { range: max(lo, other_lo)..=min(hi, other_hi), ty, span })
161151
} else {
162-
// If the range should not be treated exhaustively, fallback to checking for inclusion.
163-
if self.is_subrange(other) { Some(self.clone()) } else { None }
152+
None
164153
}
165154
}
166155

@@ -271,7 +260,7 @@ impl<'tcx> IntRange<'tcx> {
271260
.head_ctors(pcx.cx)
272261
.filter_map(|ctor| ctor.as_int_range())
273262
.filter_map(|range| {
274-
let intersection = self.intersection(pcx.cx.tcx, &range);
263+
let intersection = self.intersection(&range);
275264
let should_lint = self.suspicious_intersection(&range);
276265
if let (Some(range), 1, true) = (&intersection, row_len, should_lint) {
277266
// FIXME: for now, only check for overlapping ranges on simple range
@@ -346,8 +335,8 @@ impl<'tcx> IntRange<'tcx> {
346335
}
347336

348337
/// See `Constructor::is_covered_by`
349-
fn is_covered_by<'p>(&self, pcx: PatCtxt<'_, 'p, 'tcx>, other: &Self) -> bool {
350-
if self.intersection(pcx.cx.tcx, other).is_some() {
338+
fn is_covered_by(&self, other: &Self) -> bool {
339+
if self.intersection(other).is_some() {
351340
// Constructor splitting should ensure that all intersections we encounter are actually
352341
// inclusions.
353342
assert!(self.is_subrange(other));
@@ -694,11 +683,7 @@ impl<'tcx> Constructor<'tcx> {
694683
Wildcard => Constructor::split_wildcard(pcx),
695684
// Fast-track if the range is trivial. In particular, we don't do the overlapping
696685
// ranges check.
697-
IntRange(ctor_range)
698-
if ctor_range.treat_exhaustively(pcx.cx.tcx) && !ctor_range.is_singleton() =>
699-
{
700-
ctor_range.split(pcx, hir_id)
701-
}
686+
IntRange(ctor_range) if !ctor_range.is_singleton() => ctor_range.split(pcx, hir_id),
702687
Slice(slice @ Slice { kind: VarLen(..), .. }) => slice.split(pcx),
703688
// Any other constructor can be used unchanged.
704689
_ => smallvec![self.clone()],
@@ -740,9 +725,7 @@ impl<'tcx> Constructor<'tcx> {
740725
(Single, Single) => true,
741726
(Variant(self_id), Variant(other_id)) => self_id == other_id,
742727

743-
(IntRange(self_range), IntRange(other_range)) => {
744-
self_range.is_covered_by(pcx, other_range)
745-
}
728+
(IntRange(self_range), IntRange(other_range)) => self_range.is_covered_by(other_range),
746729
(
747730
FloatRange(self_from, self_to, self_end),
748731
FloatRange(other_from, other_to, other_end),
@@ -803,15 +786,15 @@ impl<'tcx> Constructor<'tcx> {
803786
IntRange(range) => used_ctors
804787
.iter()
805788
.filter_map(|c| c.as_int_range())
806-
.any(|other| range.is_covered_by(pcx, other)),
789+
.any(|other| range.is_covered_by(other)),
807790
Slice(slice) => used_ctors
808791
.iter()
809792
.filter_map(|c| c.as_slice())
810793
.any(|other| slice.is_covered_by(other)),
811794
// This constructor is never covered by anything else
812795
NonExhaustive => false,
813796
Str(..) | FloatRange(..) | Opaque | Wildcard => {
814-
bug!("found unexpected ctor in all_ctors: {:?}", self)
797+
span_bug!(pcx.span, "found unexpected ctor in all_ctors: {:?}", self)
815798
}
816799
}
817800
}

src/test/ui/pattern/usefulness/integer-ranges/reachability.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ fn main() {
7272
match 0usize {
7373
0..10 => {},
7474
10..20 => {},
75-
5..15 => {}, // FIXME: should be unreachable
75+
5..15 => {}, //~ ERROR unreachable pattern
7676
_ => {},
7777
}
7878
// Chars between '\u{D7FF}' and '\u{E000}' are invalid even though ranges that contain them are

src/test/ui/pattern/usefulness/integer-ranges/reachability.stderr

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,12 @@ error: unreachable pattern
124124
LL | 5..25 => {},
125125
| ^^^^^
126126

127+
error: unreachable pattern
128+
--> $DIR/reachability.rs:75:9
129+
|
130+
LL | 5..15 => {},
131+
| ^^^^^
132+
127133
error: unreachable pattern
128134
--> $DIR/reachability.rs:82:9
129135
|
@@ -142,5 +148,5 @@ error: unreachable pattern
142148
LL | BAR => {}
143149
| ^^^
144150

145-
error: aborting due to 23 previous errors
151+
error: aborting due to 24 previous errors
146152

0 commit comments

Comments
 (0)