Special-case range inclusion when the range is integral but non-exhaustive
This commit is contained in:
parent
f3752ee5d5
commit
81db2ee902
1 changed files with 27 additions and 0 deletions
|
@ -641,6 +641,15 @@ impl<'tcx> Constructor<'tcx> {
|
|||
IntRange::should_treat_range_exhaustively(tcx, ty)
|
||||
}
|
||||
|
||||
fn is_integral_range(&self) -> bool {
|
||||
let ty = match self {
|
||||
ConstantValue(value, _) => value.ty,
|
||||
ConstantRange(_, _, ty, _, _) => ty,
|
||||
_ => return false,
|
||||
};
|
||||
IntRange::is_integral(ty)
|
||||
}
|
||||
|
||||
fn variant_index_for_adt<'a>(
|
||||
&self,
|
||||
cx: &MatchCheckCtxt<'a, 'tcx>,
|
||||
|
@ -1471,6 +1480,12 @@ impl<'tcx> IntRange<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn is_subrange(&self, other: &Self) -> bool {
|
||||
let (lo, hi) = (*self.range.start(), *self.range.end());
|
||||
let (other_lo, other_hi) = (*other.range.start(), *other.range.end());
|
||||
other_lo <= lo && hi <= other_hi
|
||||
}
|
||||
|
||||
fn suspicious_intersection(&self, other: &Self) -> bool {
|
||||
// `false` in the following cases:
|
||||
// 1 ---- // 1 ---------- // 1 ---- // 1 ----
|
||||
|
@ -2300,6 +2315,8 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
|
|||
IntRange::from_pat(cx.tcx, cx.param_env, pat),
|
||||
) {
|
||||
(Some(ctor), Some(pat)) => ctor.intersection(&pat).map(|_| {
|
||||
// Constructor splitting should ensure that all intersections we encounter
|
||||
// are actually inclusions.
|
||||
let (pat_lo, pat_hi) = pat.range.into_inner();
|
||||
let (ctor_lo, ctor_hi) = ctor.range.into_inner();
|
||||
assert!(pat_lo <= ctor_lo && ctor_hi <= pat_hi);
|
||||
|
@ -2307,6 +2324,16 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
|
|||
}),
|
||||
_ => None,
|
||||
}
|
||||
} else if constructor.is_integral_range() {
|
||||
// If we have an integer range that should not be matched exhaustively, fallback to
|
||||
// checking for inclusion.
|
||||
match (
|
||||
IntRange::from_ctor(cx.tcx, cx.param_env, constructor),
|
||||
IntRange::from_pat(cx.tcx, cx.param_env, pat),
|
||||
) {
|
||||
(Some(ctor), Some(pat)) if ctor.is_subrange(&pat) => Some(PatStack::default()),
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
// Fallback for non-ranges and ranges that involve
|
||||
// floating-point numbers, which are not conveniently handled
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue