Skip to content

Commit 75a5088

Browse files
committed
Avoid converting through Constructor when subtracting ranges
1 parent c6c8625 commit 75a5088

File tree

1 file changed

+29
-38
lines changed

1 file changed

+29
-38
lines changed

src/librustc_mir/hair/pattern/_match.rs

Lines changed: 29 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -763,35 +763,30 @@ impl<'tcx> Constructor<'tcx> {
763763
remaining_ctors
764764
}
765765
ConstantRange(..) | ConstantValue(..) => {
766-
if let Some(_self_range) = IntRange::from_ctor(tcx, param_env, self) {
767-
let mut remaining_ctors = vec![self.clone()];
768-
for other_ctor in other_ctors {
769-
if other_ctor == self {
770-
// If a constructor appears in a `match` arm, we can
766+
if let Some(self_range) = IntRange::from_ctor(tcx, param_env, self) {
767+
let mut remaining_ranges = vec![self_range.clone()];
768+
let other_ranges = other_ctors
769+
.into_iter()
770+
.filter_map(|c| IntRange::from_ctor(tcx, param_env, c));
771+
for other_range in other_ranges {
772+
if other_range == self_range {
773+
// If the `self` range appears directly in a `match` arm, we can
771774
// eliminate it straight away.
772-
remaining_ctors = vec![]
773-
} else if let Some(interval) =
774-
IntRange::from_ctor(tcx, param_env, other_ctor)
775-
{
776-
// Refine the required constructors for the type by subtracting
777-
// the range defined by the current constructor pattern.
778-
remaining_ctors =
779-
interval.subtract_from(tcx, param_env, remaining_ctors);
775+
remaining_ranges = vec![];
776+
} else {
777+
// Otherwise explicitely compute the remaining ranges.
778+
remaining_ranges = other_range.subtract_from(remaining_ranges);
780779
}
781780

782-
// If the constructor patterns that have been considered so far
783-
// already cover the entire range of values, then we know the
784-
// constructor is not missing, and we can move on to the next one.
785-
if remaining_ctors.is_empty() {
781+
// If the ranges that have been considered so far already cover the entire
782+
// range of values, we can return early.
783+
if remaining_ranges.is_empty() {
786784
break;
787785
}
788786
}
789787

790-
// If a constructor has not been matched, then it is missing.
791-
// We add `remaining_ctors` instead of `self`, because then we can
792-
// provide more detailed error information about precisely which
793-
// ranges have been omitted.
794-
remaining_ctors
788+
// Convert the ranges back into constructors
789+
remaining_ranges.into_iter().map(|range| range.into_ctor(tcx)).collect()
795790
} else {
796791
if other_ctors.iter().any(|c| {
797792
c == self
@@ -1418,38 +1413,27 @@ impl<'tcx> IntRange<'tcx> {
14181413

14191414
/// Returns a collection of ranges that spans the values covered by `ranges`, subtracted
14201415
/// by the values covered by `self`: i.e., `ranges \ self` (in set notation).
1421-
fn subtract_from(
1422-
self,
1423-
tcx: TyCtxt<'tcx>,
1424-
param_env: ty::ParamEnv<'tcx>,
1425-
ranges: Vec<Constructor<'tcx>>,
1426-
) -> Vec<Constructor<'tcx>> {
1427-
let ranges = ranges
1428-
.into_iter()
1429-
.filter_map(|r| IntRange::from_ctor(tcx, param_env, &r).map(|i| i.range));
1416+
fn subtract_from(self, ranges: Vec<IntRange<'tcx>>) -> Vec<IntRange<'tcx>> {
14301417
let mut remaining_ranges = vec![];
14311418
let ty = self.ty;
14321419
let span = self.span;
14331420
let (lo, hi) = self.range.into_inner();
14341421
for subrange in ranges {
1435-
let (subrange_lo, subrange_hi) = subrange.into_inner();
1422+
let (subrange_lo, subrange_hi) = subrange.range.into_inner();
14361423
if lo > subrange_hi || subrange_lo > hi {
14371424
// The pattern doesn't intersect with the subrange at all,
14381425
// so the subrange remains untouched.
1439-
remaining_ranges
1440-
.push(IntRange { range: subrange_lo..=subrange_hi, ty, span }.into_ctor(tcx));
1426+
remaining_ranges.push(IntRange { range: subrange_lo..=subrange_hi, ty, span });
14411427
} else {
14421428
if lo > subrange_lo {
14431429
// The pattern intersects an upper section of the
14441430
// subrange, so a lower section will remain.
1445-
remaining_ranges
1446-
.push(IntRange { range: subrange_lo..=(lo - 1), ty, span }.into_ctor(tcx));
1431+
remaining_ranges.push(IntRange { range: subrange_lo..=(lo - 1), ty, span });
14471432
}
14481433
if hi < subrange_hi {
14491434
// The pattern intersects a lower section of the
14501435
// subrange, so an upper section will remain.
1451-
remaining_ranges
1452-
.push(IntRange { range: (hi + 1)..=subrange_hi, ty, span }.into_ctor(tcx));
1436+
remaining_ranges.push(IntRange { range: (hi + 1)..=subrange_hi, ty, span });
14531437
}
14541438
}
14551439
}
@@ -1491,6 +1475,13 @@ impl<'tcx> IntRange<'tcx> {
14911475
}
14921476
}
14931477

1478+
// Ignore spans when comparing, they don't carry semantic information as they are only for lints.
1479+
impl<'tcx> std::cmp::PartialEq for IntRange<'tcx> {
1480+
fn eq(&self, other: &Self) -> bool {
1481+
self.range == other.range && self.ty == other.ty
1482+
}
1483+
}
1484+
14941485
// A struct to compute a set of constructors equivalent to `all_ctors \ used_ctors`.
14951486
struct MissingConstructors<'tcx> {
14961487
tcx: TyCtxt<'tcx>,

0 commit comments

Comments
 (0)