about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_mir/build/matches/simplify.rs34
-rw-r--r--src/test/ui/pattern/irrefutable-exhaustive-integer-binding.rs8
2 files changed, 41 insertions, 1 deletions
diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs
index cfea357334f..328b330f762 100644
--- a/src/librustc_mir/build/matches/simplify.rs
+++ b/src/librustc_mir/build/matches/simplify.rs
@@ -26,6 +26,10 @@ use build::{BlockAnd, BlockAndExtension, Builder};
 use build::matches::{Ascription, Binding, MatchPair, Candidate};
 use hair::*;
 use rustc::mir::*;
+use rustc::ty;
+use rustc::ty::layout::{Integer, IntegerExt, Size};
+use syntax::attr::{SignedInt, UnsignedInt};
+use rustc::hir::RangeEnd;
 
 use std::mem;
 
@@ -62,6 +66,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                                  match_pair: MatchPair<'pat, 'tcx>,
                                  candidate: &mut Candidate<'pat, 'tcx>)
                                  -> Result<(), MatchPair<'pat, 'tcx>> {
+        let tcx = self.hir.tcx();
         match *match_pair.pattern.kind {
             PatternKind::AscribeUserType { ref subpattern, ref user_ty, user_ty_span } => {
                 candidate.ascriptions.push(Ascription {
@@ -104,7 +109,34 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 Err(match_pair)
             }
 
-            PatternKind::Range { .. } => {
+            PatternKind::Range { lo, hi, ty, end } => {
+                let range = match ty.sty {
+                    ty::Char => {
+                        Some(('\u{0000}' as u128, '\u{10FFFF}' as u128, Size::from_bits(32)))
+                    }
+                    ty::Int(ity) => {
+                        // FIXME(49937): refactor these bit manipulations into interpret.
+                        let size = Integer::from_attr(&tcx, SignedInt(ity)).size();
+                        let min = 1u128 << (size.bits() - 1);
+                        let max = (1u128 << (size.bits() - 1)) - 1;
+                        Some((min, max, size))
+                    }
+                    ty::Uint(uty) => {
+                        // FIXME(49937): refactor these bit manipulations into interpret.
+                        let size = Integer::from_attr(&tcx, UnsignedInt(uty)).size();
+                        let max = !0u128 >> (128 - size.bits());
+                        Some((0, max, size))
+                    }
+                    _ => None,
+                };
+                if let Some((min, max, sz)) = range {
+                    if let (Some(lo), Some(hi)) = (lo.val.try_to_bits(sz), hi.val.try_to_bits(sz)) {
+                        if lo <= min && (hi > max || hi == max && end == RangeEnd::Included) {
+                            // Irrefutable pattern match.
+                            return Ok(());
+                        }
+                    }
+                }
                 Err(match_pair)
             }
 
diff --git a/src/test/ui/pattern/irrefutable-exhaustive-integer-binding.rs b/src/test/ui/pattern/irrefutable-exhaustive-integer-binding.rs
new file mode 100644
index 00000000000..ff065882d96
--- /dev/null
+++ b/src/test/ui/pattern/irrefutable-exhaustive-integer-binding.rs
@@ -0,0 +1,8 @@
+// run-pass
+
+fn main() {
+    let -2147483648..=2147483647 = 1;
+    let 0..=255 = 0u8;
+    let -128..=127 = 0i8;
+    let '\u{0000}'..='\u{10FFFF}' = 'v';
+}