diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 5d990dfa8dfe32d378776050c99d5366ee4a4159..60a8c89995a00b5b473746ef024af79b1659d7b3 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -35,6 +35,7 @@ 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 @@ fn variant_index_for_adt(&self, adt: &'tcx ty::AdtDef) -> usize { } } -#[derive(Clone)] +#[derive(Clone, Debug)] pub enum Usefulness<'tcx> { Useful, UsefulWithWitness(Vec>), @@ -290,7 +291,7 @@ fn is_useful(&self) -> bool { } } -#[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>); impl<'tcx> Witness<'tcx> { @@ -418,10 +419,6 @@ fn apply_constructor<'a>( /// 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