Refactor condition
This commit is contained in:
parent
25ba9118ff
commit
af366b0eb8
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user