Skip to content

Commit 81db2ee

Browse files
committed
Special-case range inclusion when the range is integral but non-exhaustive
1 parent f3752ee commit 81db2ee

File tree

1 file changed

+27
-0
lines changed

1 file changed

+27
-0
lines changed

src/librustc_mir/hair/pattern/_match.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,15 @@ impl<'tcx> Constructor<'tcx> {
641641
IntRange::should_treat_range_exhaustively(tcx, ty)
642642
}
643643

644+
fn is_integral_range(&self) -> bool {
645+
let ty = match self {
646+
ConstantValue(value, _) => value.ty,
647+
ConstantRange(_, _, ty, _, _) => ty,
648+
_ => return false,
649+
};
650+
IntRange::is_integral(ty)
651+
}
652+
644653
fn variant_index_for_adt<'a>(
645654
&self,
646655
cx: &MatchCheckCtxt<'a, 'tcx>,
@@ -1471,6 +1480,12 @@ impl<'tcx> IntRange<'tcx> {
14711480
}
14721481
}
14731482

1483+
fn is_subrange(&self, other: &Self) -> bool {
1484+
let (lo, hi) = (*self.range.start(), *self.range.end());
1485+
let (other_lo, other_hi) = (*other.range.start(), *other.range.end());
1486+
other_lo <= lo && hi <= other_hi
1487+
}
1488+
14741489
fn suspicious_intersection(&self, other: &Self) -> bool {
14751490
// `false` in the following cases:
14761491
// 1 ---- // 1 ---------- // 1 ---- // 1 ----
@@ -2300,13 +2315,25 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
23002315
IntRange::from_pat(cx.tcx, cx.param_env, pat),
23012316
) {
23022317
(Some(ctor), Some(pat)) => ctor.intersection(&pat).map(|_| {
2318+
// Constructor splitting should ensure that all intersections we encounter
2319+
// are actually inclusions.
23032320
let (pat_lo, pat_hi) = pat.range.into_inner();
23042321
let (ctor_lo, ctor_hi) = ctor.range.into_inner();
23052322
assert!(pat_lo <= ctor_lo && ctor_hi <= pat_hi);
23062323
PatStack::default()
23072324
}),
23082325
_ => None,
23092326
}
2327+
} else if constructor.is_integral_range() {
2328+
// If we have an integer range that should not be matched exhaustively, fallback to
2329+
// checking for inclusion.
2330+
match (
2331+
IntRange::from_ctor(cx.tcx, cx.param_env, constructor),
2332+
IntRange::from_pat(cx.tcx, cx.param_env, pat),
2333+
) {
2334+
(Some(ctor), Some(pat)) if ctor.is_subrange(&pat) => Some(PatStack::default()),
2335+
_ => None,
2336+
}
23102337
} else {
23112338
// Fallback for non-ranges and ranges that involve
23122339
// floating-point numbers, which are not conveniently handled

0 commit comments

Comments
 (0)