diff options
| author | Nadrieril <nadrieril+git@gmail.com> | 2020-11-28 21:23:38 +0000 |
|---|---|---|
| committer | Nadrieril <nadrieril+git@gmail.com> | 2020-11-28 21:23:38 +0000 |
| commit | d8983655c1735c302fd0d5784f3413fd9cab89e4 (patch) | |
| tree | 925e191e0fa60c63914a1218528d33d65a54b170 | |
| parent | 4ae328bef47dffcbf363e5ae873f419c06a5511d (diff) | |
| download | rust-d8983655c1735c302fd0d5784f3413fd9cab89e4.tar.gz rust-d8983655c1735c302fd0d5784f3413fd9cab89e4.zip | |
Correctly detect `usize`/`isize` range overlaps
3 files changed, 20 insertions, 31 deletions
diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs index 62b4468eeb3..34c415987d8 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs @@ -58,12 +58,6 @@ impl<'tcx> IntRange<'tcx> { (*self.range.start(), *self.range.end()) } - /// Don't treat `usize`/`isize` exhaustively unless the `precise_pointer_size_matching` feature - /// is enabled. - fn treat_exhaustively(&self, tcx: TyCtxt<'tcx>) -> bool { - !self.ty.is_ptr_sized_integral() || tcx.features().precise_pointer_size_matching - } - #[inline] fn integral_size_and_signed_bias(tcx: TyCtxt<'tcx>, ty: Ty<'_>) -> Option<(Size, u128)> { match *ty.kind() { @@ -147,20 +141,15 @@ impl<'tcx> IntRange<'tcx> { other.range.start() <= self.range.start() && self.range.end() <= other.range.end() } - fn intersection(&self, tcx: TyCtxt<'tcx>, other: &Self) -> Option<Self> { + fn intersection(&self, other: &Self) -> Option<Self> { let ty = self.ty; let (lo, hi) = self.boundaries(); let (other_lo, other_hi) = other.boundaries(); - if self.treat_exhaustively(tcx) { - if lo <= other_hi && other_lo <= hi { - let span = other.span; - Some(IntRange { range: max(lo, other_lo)..=min(hi, other_hi), ty, span }) - } else { - None - } + if lo <= other_hi && other_lo <= hi { + let span = other.span; + Some(IntRange { range: max(lo, other_lo)..=min(hi, other_hi), ty, span }) } else { - // If the range should not be treated exhaustively, fallback to checking for inclusion. - if self.is_subrange(other) { Some(self.clone()) } else { None } + None } } @@ -271,7 +260,7 @@ impl<'tcx> IntRange<'tcx> { .head_ctors(pcx.cx) .filter_map(|ctor| ctor.as_int_range()) .filter_map(|range| { - let intersection = self.intersection(pcx.cx.tcx, &range); + let intersection = self.intersection(&range); let should_lint = self.suspicious_intersection(&range); if let (Some(range), 1, true) = (&intersection, row_len, should_lint) { // FIXME: for now, only check for overlapping ranges on simple range @@ -346,8 +335,8 @@ impl<'tcx> IntRange<'tcx> { } /// See `Constructor::is_covered_by` - fn is_covered_by<'p>(&self, pcx: PatCtxt<'_, 'p, 'tcx>, other: &Self) -> bool { - if self.intersection(pcx.cx.tcx, other).is_some() { + fn is_covered_by(&self, other: &Self) -> bool { + if self.intersection(other).is_some() { // Constructor splitting should ensure that all intersections we encounter are actually // inclusions. assert!(self.is_subrange(other)); @@ -694,11 +683,7 @@ impl<'tcx> Constructor<'tcx> { Wildcard => Constructor::split_wildcard(pcx), // Fast-track if the range is trivial. In particular, we don't do the overlapping // ranges check. - IntRange(ctor_range) - if ctor_range.treat_exhaustively(pcx.cx.tcx) && !ctor_range.is_singleton() => - { - ctor_range.split(pcx, hir_id) - } + IntRange(ctor_range) if !ctor_range.is_singleton() => ctor_range.split(pcx, hir_id), Slice(slice @ Slice { kind: VarLen(..), .. }) => slice.split(pcx), // Any other constructor can be used unchanged. _ => smallvec![self.clone()], @@ -740,9 +725,7 @@ impl<'tcx> Constructor<'tcx> { (Single, Single) => true, (Variant(self_id), Variant(other_id)) => self_id == other_id, - (IntRange(self_range), IntRange(other_range)) => { - self_range.is_covered_by(pcx, other_range) - } + (IntRange(self_range), IntRange(other_range)) => self_range.is_covered_by(other_range), ( FloatRange(self_from, self_to, self_end), FloatRange(other_from, other_to, other_end), @@ -803,7 +786,7 @@ impl<'tcx> Constructor<'tcx> { IntRange(range) => used_ctors .iter() .filter_map(|c| c.as_int_range()) - .any(|other| range.is_covered_by(pcx, other)), + .any(|other| range.is_covered_by(other)), Slice(slice) => used_ctors .iter() .filter_map(|c| c.as_slice()) @@ -811,7 +794,7 @@ impl<'tcx> Constructor<'tcx> { // This constructor is never covered by anything else NonExhaustive => false, Str(..) | FloatRange(..) | Opaque | Wildcard => { - bug!("found unexpected ctor in all_ctors: {:?}", self) + span_bug!(pcx.span, "found unexpected ctor in all_ctors: {:?}", self) } } } diff --git a/src/test/ui/pattern/usefulness/integer-ranges/reachability.rs b/src/test/ui/pattern/usefulness/integer-ranges/reachability.rs index 9078e65f667..6516925e939 100644 --- a/src/test/ui/pattern/usefulness/integer-ranges/reachability.rs +++ b/src/test/ui/pattern/usefulness/integer-ranges/reachability.rs @@ -72,7 +72,7 @@ fn main() { match 0usize { 0..10 => {}, 10..20 => {}, - 5..15 => {}, // FIXME: should be unreachable + 5..15 => {}, //~ ERROR unreachable pattern _ => {}, } // Chars between '\u{D7FF}' and '\u{E000}' are invalid even though ranges that contain them are diff --git a/src/test/ui/pattern/usefulness/integer-ranges/reachability.stderr b/src/test/ui/pattern/usefulness/integer-ranges/reachability.stderr index 8baf0d50c88..e6878d950d6 100644 --- a/src/test/ui/pattern/usefulness/integer-ranges/reachability.stderr +++ b/src/test/ui/pattern/usefulness/integer-ranges/reachability.stderr @@ -125,6 +125,12 @@ LL | 5..25 => {}, | ^^^^^ error: unreachable pattern + --> $DIR/reachability.rs:75:9 + | +LL | 5..15 => {}, + | ^^^^^ + +error: unreachable pattern --> $DIR/reachability.rs:82:9 | LL | '\u{D7FF}'..='\u{E000}' => {}, @@ -142,5 +148,5 @@ error: unreachable pattern LL | BAR => {} | ^^^ -error: aborting due to 23 previous errors +error: aborting due to 24 previous errors |
