/// For example, the pattern `-128...127i8` is encoded as `0..=255`.
/// This makes comparisons and arithmetic on interval endpoints much more
/// straightforward. See `signed_bias` for details.
+///
+/// `IntRange` is never used to encode an empty range or a "range" that wraps
+/// around the (offset) space: i.e. `range.lo <= range.hi`.
struct IntRange<'tcx> {
pub range: RangeInclusive<u128>,
pub ty: Ty<'tcx>,
}
}
- /// Given an `IntRange` corresponding to a pattern in a `match` and a collection of
- /// ranges corresponding to the domain of values of a type (say, an integer), return
- /// a new collection of ranges corresponding to the original ranges minus the ranges
- /// covered by the `IntRange`.
+ /// Return a collection of ranges that spans the values covered by `ranges`, subtracted
+ /// by the values covered by `self`: i.e. `ranges \ self` (in set notation).
fn subtract_from(self,
tcx: TyCtxt<'_, 'tcx, 'tcx>,
ranges: Vec<Constructor<'tcx>>)
}
}
-// Find those constructors that are not matched by any non-wildcard patterns in the current column.
+// Return a set of constructors equivalent to `all_ctors \ used_ctors`.
fn compute_missing_ctors<'a, 'tcx: 'a>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
all_ctors: &Vec<Constructor<'tcx>>,
if let Some(constructors) = pat_constructors(cx, v[0], pcx) {
debug!("is_useful - expanding constructors: {:#?}", constructors);
- split_grouped_constructors(cx.tcx, constructors, matrix, v, pcx.ty).into_iter().map(|c|
+ split_grouped_constructors(cx.tcx, constructors, matrix, pcx.ty).into_iter().map(|c|
is_useful_specialized(cx, matrix, v, c.clone(), pcx.ty, witness)
).find(|result| result.is_useful()).unwrap_or(NotUseful)
} else {
// be a privately-empty enum is when the exhaustive_patterns
// feature flag is not present, so this is only
// needed for that case.
+
+ // Find those constructors that are not matched by any non-wildcard patterns in the
+ // current column.
let missing_ctors = compute_missing_ctors(cx.tcx, &all_ctors, &used_ctors);
let is_privately_empty = all_ctors.is_empty() && !cx.is_uninhabited(pcx.ty);
let is_non_exhaustive = is_privately_empty || is_declared_nonexhaustive;
if missing_ctors.is_empty() && !is_non_exhaustive {
- split_grouped_constructors(cx.tcx, all_ctors, matrix, v, pcx.ty).into_iter().map(|c| {
+ split_grouped_constructors(cx.tcx, all_ctors, matrix, pcx.ty).into_iter().map(|c| {
is_useful_specialized(cx, matrix, v, c.clone(), pcx.ty, witness)
}).find(|result| result.is_useful()).unwrap_or(NotUseful)
} else {
tcx: TyCtxt<'a, 'tcx, 'tcx>,
ctors: Vec<Constructor<'tcx>>,
&Matrix(ref m): &Matrix<'p, 'tcx>,
- p: &[&'p Pattern<'tcx>],
ty: Ty<'tcx>,
) -> Vec<Constructor<'tcx>> {
- let pat = &p[0];
-
let mut split_ctors = Vec::with_capacity(ctors.len());
for ctor in ctors.into_iter() {
// of the new pattern `p_({m + 1},1)` (here `pat`) and the constructor range.
// Anything else is irrelevant, because it is guaranteed to result in `NotUseful`,
// which is the default case anyway, and can be ignored.
- let mut ctor_range = IntRange::from_ctor(tcx, &ctor).unwrap();
- if let Some(pat_range) = IntRange::from_pat(tcx, pat) {
- if let Some(new_range) = ctor_range.intersection(&pat_range) {
- ctor_range = new_range;
- } else {
- // If the intersection between `pat` and the constructor is empty, the
- // entire range is `NotUseful`.
- continue;
- }
- } else {
- match pat.kind {
- box PatternKind::Wild => {
- // A wild pattern matches the entire range of values,
- // so the current values are fine.
- }
- // If the pattern is not a value (i.e. a degenerate range), a range or a
- // wildcard (which stands for the entire range), then it's guaranteed to
- // be `NotUseful`.
- _ => continue,
- }
- }
+ let ctor_range = IntRange::from_ctor(tcx, &ctor).unwrap();
+
// We're going to collect all the endpoints in the new pattern so we can create
// subranges between them.
// If there's a single point, we need to identify it as belonging