Skip to content

Commit 0a18610

Browse files
committed
Move range exhaustiveness check to IntRange::intersection
Only IntRange should need to worry about range exhaustiveness really.
1 parent 81db2ee commit 0a18610

File tree

1 file changed

+14
-36
lines changed

1 file changed

+14
-36
lines changed

src/librustc_mir/hair/pattern/_match.rs

Lines changed: 14 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -630,17 +630,6 @@ impl<'tcx> Constructor<'tcx> {
630630
}
631631
}
632632

633-
// Whether to evaluate a constructor using exhaustive integer matching. This is true if the
634-
// constructor is a range or constant with an integer type.
635-
fn is_range_and_should_match_exhaustively(&self, tcx: TyCtxt<'tcx>) -> bool {
636-
let ty = match self {
637-
ConstantValue(value, _) => value.ty,
638-
ConstantRange(_, _, ty, _, _) => ty,
639-
_ => return false,
640-
};
641-
IntRange::should_treat_range_exhaustively(tcx, ty)
642-
}
643-
644633
fn is_integral_range(&self) -> bool {
645634
let ty = match self {
646635
ConstantValue(value, _) => value.ty,
@@ -1468,24 +1457,23 @@ impl<'tcx> IntRange<'tcx> {
14681457
remaining_ranges
14691458
}
14701459

1471-
fn intersection(&self, other: &Self) -> Option<Self> {
1460+
fn intersection(&self, tcx: TyCtxt<'tcx>, other: &Self) -> Option<Self> {
14721461
let ty = self.ty;
14731462
let (lo, hi) = (*self.range.start(), *self.range.end());
14741463
let (other_lo, other_hi) = (*other.range.start(), *other.range.end());
1475-
if lo <= other_hi && other_lo <= hi {
1476-
let span = other.span;
1477-
Some(IntRange { range: max(lo, other_lo)..=min(hi, other_hi), ty, span })
1464+
if Self::should_treat_range_exhaustively(tcx, ty) {
1465+
if lo <= other_hi && other_lo <= hi {
1466+
let span = other.span;
1467+
Some(IntRange { range: max(lo, other_lo)..=min(hi, other_hi), ty, span })
1468+
} else {
1469+
None
1470+
}
14781471
} else {
1479-
None
1472+
// If the range sould not be treated exhaustively, fallback to checking for inclusion.
1473+
if other_lo <= lo && hi <= other_hi { Some(self.clone()) } else { None }
14801474
}
14811475
}
14821476

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-
14891477
fn suspicious_intersection(&self, other: &Self) -> bool {
14901478
// `false` in the following cases:
14911479
// 1 ---- // 1 ---------- // 1 ---- // 1 ----
@@ -1913,7 +1901,7 @@ fn split_grouped_constructors<'p, 'tcx>(
19131901

19141902
for ctor in ctors.into_iter() {
19151903
match ctor {
1916-
ConstantRange(..) if ctor.is_range_and_should_match_exhaustively(tcx) => {
1904+
ConstantRange(..) if IntRange::should_treat_range_exhaustively(tcx, ty) => {
19171905
// We only care about finding all the subranges within the range of the constructor
19181906
// range. Anything else is irrelevant, because it is guaranteed to result in
19191907
// `NotUseful`, which is the default case anyway, and can be ignored.
@@ -1951,7 +1939,7 @@ fn split_grouped_constructors<'p, 'tcx>(
19511939
IntRange::from_pat(tcx, param_env, row.head()).map(|r| (r, row.len()))
19521940
})
19531941
.flat_map(|(range, row_len)| {
1954-
let intersection = ctor_range.intersection(&range);
1942+
let intersection = ctor_range.intersection(tcx, &range);
19551943
let should_lint = ctor_range.suspicious_intersection(&range);
19561944
if let (Some(range), 1, true) = (&intersection, row_len, should_lint) {
19571945
// FIXME: for now, only check for overlapping ranges on simple range
@@ -2309,12 +2297,12 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
23092297
// If the constructor is a:
23102298
// - Single value: add a row if the pattern contains the constructor.
23112299
// - Range: add a row if the constructor intersects the pattern.
2312-
if constructor.is_range_and_should_match_exhaustively(cx.tcx) {
2300+
if constructor.is_integral_range() {
23132301
match (
23142302
IntRange::from_ctor(cx.tcx, cx.param_env, constructor),
23152303
IntRange::from_pat(cx.tcx, cx.param_env, pat),
23162304
) {
2317-
(Some(ctor), Some(pat)) => ctor.intersection(&pat).map(|_| {
2305+
(Some(ctor), Some(pat)) => ctor.intersection(cx.tcx, &pat).map(|_| {
23182306
// Constructor splitting should ensure that all intersections we encounter
23192307
// are actually inclusions.
23202308
let (pat_lo, pat_hi) = pat.range.into_inner();
@@ -2324,16 +2312,6 @@ fn specialize_one_pattern<'p, 'a: 'p, 'q: 'p, 'tcx>(
23242312
}),
23252313
_ => None,
23262314
}
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-
}
23372315
} else {
23382316
// Fallback for non-ranges and ranges that involve
23392317
// floating-point numbers, which are not conveniently handled

0 commit comments

Comments
 (0)