about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNadrieril <nadrieril+git@gmail.com>2020-11-28 21:23:38 +0000
committerNadrieril <nadrieril+git@gmail.com>2020-11-28 21:23:38 +0000
commitd8983655c1735c302fd0d5784f3413fd9cab89e4 (patch)
tree925e191e0fa60c63914a1218528d33d65a54b170
parent4ae328bef47dffcbf363e5ae873f419c06a5511d (diff)
downloadrust-d8983655c1735c302fd0d5784f3413fd9cab89e4.tar.gz
rust-d8983655c1735c302fd0d5784f3413fd9cab89e4.zip
Correctly detect `usize`/`isize` range overlaps
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs41
-rw-r--r--src/test/ui/pattern/usefulness/integer-ranges/reachability.rs2
-rw-r--r--src/test/ui/pattern/usefulness/integer-ranges/reachability.stderr8
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