about summary refs log tree commit diff
diff options
context:
space:
mode:
authorvarkor <github@varkor.com>2018-06-22 23:52:56 +0100
committervarkor <github@varkor.com>2018-08-16 20:09:05 +0100
commitaf366b0eb86eb7111150b4143167440532e09520 (patch)
treec85a8f7ec529eb2179982f5818a3a0d2fc7c7963
parent25ba9118ff3d3f6b8d05efb7995c4d53a55841b8 (diff)
downloadrust-af366b0eb86eb7111150b4143167440532e09520.tar.gz
rust-af366b0eb86eb7111150b4143167440532e09520.zip
Refactor condition
-rw-r--r--src/librustc_mir/hair/pattern/_match.rs58
1 files changed, 27 insertions, 31 deletions
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs
index 5d990dfa8df..60a8c89995a 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir/hair/pattern/_match.rs
@@ -35,6 +35,7 @@ use arena::TypedArena;
 use std::cmp::{self, Ordering};
 use std::fmt;
 use std::iter::{FromIterator, IntoIterator};
+use std::ops::RangeInclusive;
 
 pub fn expand_pattern<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>, pat: Pattern<'tcx>)
                                 -> &'a Pattern<'tcx>
@@ -274,7 +275,7 @@ impl<'tcx> Constructor<'tcx> {
     }
 }
 
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 pub enum Usefulness<'tcx> {
     Useful,
     UsefulWithWitness(Vec<Witness<'tcx>>),
@@ -290,7 +291,7 @@ impl<'tcx> Usefulness<'tcx> {
     }
 }
 
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
 pub enum WitnessPreference {
     ConstructWitness,
     LeaveOutWitness
@@ -303,7 +304,7 @@ struct PatternContext<'tcx> {
 }
 
 /// A stack of patterns in reverse order of construction
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 pub struct Witness<'tcx>(Vec<Pattern<'tcx>>);
 
 impl<'tcx> Witness<'tcx> {
@@ -418,10 +419,6 @@ impl<'tcx> Witness<'tcx> {
 /// but is instead bounded by the maximum fixed length of slice patterns in
 /// the column of patterns being analyzed.
 ///
-/// This intentionally does not list ConstantValue specializations for
-/// non-booleans, because we currently assume that there is always a
-/// "non-standard constant" that matches. See issue #12483.
-///
 /// We make sure to omit constructors that are statically impossible. eg for
 /// Option<!> we do not include Some(_) in the returned list of constructors.
 fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
@@ -530,7 +527,7 @@ fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>(
     //     `[true, ..]`
     //     `[.., false]`
     // Then any slice of length ≥1 that matches one of these two
-    // patterns can be  be trivially turned to a slice of any
+    // patterns can be trivially turned to a slice of any
     // other length ≥1 that matches them and vice-versa - for
     // but the slice from length 2 `[false, true]` that matches neither
     // of these patterns can't be turned to a slice from length 1 that
@@ -823,33 +820,32 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
         // as patterns in the `match` expression, but did not.
         let mut missing_ctors = vec![];
         for req_ctor in &all_ctors {
-            if consider_value_constructors {
-                let mut refined_ctors = vec![req_ctor.clone()];
-                for used_ctor in &used_ctors {
-                    // Refine the required constructors for the type by subtracting
-                    // the range defined by the current constructor pattern.
-                    refined_ctors = match IntRange::from_ctor(cx.tcx, used_ctor) {
-                        Some(interval) => interval.subtract_from(cx.tcx, refined_ctors),
-                        None => refined_ctors,
-                    };
-                    // If the constructor patterns that have been considered so far
-                    // already cover the entire range of values, then we the
-                    // constructor is not missing, and we can move on to the next one.
-                    if refined_ctors.is_empty() {
-                        break;
+            let mut refined_ctors = vec![req_ctor.clone()];
+            for used_ctor in &used_ctors {
+                if used_ctor == req_ctor {
+                    // If a constructor appears in a `match` arm, we can
+                    // eliminate it straight away.
+                    refined_ctors = vec![]
+                } else if exhaustive_integer_patterns {
+                    if let Some(interval) = IntRange::from_ctor(cx.tcx, used_ctor) {
+                        // Refine the required constructors for the type by subtracting
+                        // the range defined by the current constructor pattern.
+                        refined_ctors = interval.subtract_from(cx.tcx, refined_ctors);
                     }
                 }
-                // If a constructor has not been matched, then it is missing.
-                // We add `refined_ctors` instead of `req_ctor`, because then we can
-                // provide more detailed error information about precisely which
-                // ranges have been omitted.
-                missing_ctors.extend(refined_ctors);
-            } else {
-                // A constructor is missing if it never appears in a `match` arm.
-                if !used_ctors.iter().any(|used_ctor| used_ctor == req_ctor) {
-                    missing_ctors.push(req_ctor.clone());
+
+                // If the constructor patterns that have been considered so far
+                // already cover the entire range of values, then we the
+                // constructor is not missing, and we can move on to the next one.
+                if refined_ctors.is_empty() {
+                    break;
                 }
             }
+            // If a constructor has not been matched, then it is missing.
+            // We add `refined_ctors` instead of `req_ctor`, because then we can
+            // provide more detailed error information about precisely which
+            // ranges have been omitted.
+            missing_ctors.extend(refined_ctors);
         }
 
         // `missing_ctors` is the set of constructors from the same type as the