Skip to content

Commit fa256f7

Browse files
committed
Eagerly convert ranges to IntRange
That way no `ConstantRange` or `ConstantValue` ever needs to be converted to `IntRange`.
1 parent fbea28b commit fa256f7

File tree

1 file changed

+63
-58
lines changed

1 file changed

+63
-58
lines changed

src/librustc_mir/hair/pattern/_match.rs

Lines changed: 63 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -586,8 +586,7 @@ enum Constructor<'tcx> {
586586
ConstantValue(&'tcx ty::Const<'tcx>, Span),
587587
/// Ranges of integer literal values (`2`, `2..=5` or `2..5`).
588588
IntRange(IntRange<'tcx>),
589-
// TODO: non-integer
590-
/// Ranges of literal values (`2.0..=5.2`).
589+
/// Ranges of non-integer literal values (`2.0..=5.2`).
591590
ConstantRange(u128, u128, Ty<'tcx>, RangeEnd, Span),
592591
/// Array patterns of length `n`.
593592
FixedLenSlice(u64),
@@ -626,13 +625,10 @@ impl<'tcx> Constructor<'tcx> {
626625
}
627626

628627
fn is_integral_range(&self) -> bool {
629-
let ty = match self {
630-
ConstantValue(value, _) => value.ty,
631-
ConstantRange(_, _, ty, _, _) => ty,
628+
match self {
632629
IntRange(_) => return true,
633630
_ => return false,
634631
};
635-
IntRange::is_integral(ty)
636632
}
637633

638634
fn variant_index_for_adt<'a>(
@@ -659,7 +655,7 @@ impl<'tcx> Constructor<'tcx> {
659655
param_env: ty::ParamEnv<'tcx>,
660656
other_ctors: &Vec<Constructor<'tcx>>,
661657
) -> Vec<Constructor<'tcx>> {
662-
match *self {
658+
match self {
663659
// Those constructors can only match themselves.
664660
Single | Variant(_) => {
665661
if other_ctors.iter().any(|c| c == self) {
@@ -668,7 +664,7 @@ impl<'tcx> Constructor<'tcx> {
668664
vec![self.clone()]
669665
}
670666
}
671-
FixedLenSlice(self_len) => {
667+
&FixedLenSlice(self_len) => {
672668
let overlaps = |c: &Constructor<'_>| match *c {
673669
FixedLenSlice(other_len) => other_len == self_len,
674670
VarLenSlice(prefix, suffix) => prefix + suffix <= self_len,
@@ -739,41 +735,39 @@ impl<'tcx> Constructor<'tcx> {
739735

740736
remaining_ctors
741737
}
742-
IntRange(..) | ConstantRange(..) | ConstantValue(..) => {
743-
if let Some(self_range) = IntRange::from_ctor(tcx, param_env, self) {
744-
let mut remaining_ranges = vec![self_range.clone()];
745-
let other_ranges = other_ctors
746-
.into_iter()
747-
.filter_map(|c| IntRange::from_ctor(tcx, param_env, c));
748-
for other_range in other_ranges {
749-
if other_range == self_range {
750-
// If the `self` range appears directly in a `match` arm, we can
751-
// eliminate it straight away.
752-
remaining_ranges = vec![];
753-
} else {
754-
// Otherwise explicitely compute the remaining ranges.
755-
remaining_ranges = other_range.subtract_from(remaining_ranges);
756-
}
738+
IntRange(self_range) => {
739+
let mut remaining_ranges = vec![self_range.clone()];
740+
let other_ranges =
741+
other_ctors.into_iter().filter_map(|c| IntRange::from_ctor(tcx, param_env, c));
742+
for other_range in other_ranges {
743+
if other_range == *self_range {
744+
// If the `self` range appears directly in a `match` arm, we can
745+
// eliminate it straight away.
746+
remaining_ranges = vec![];
747+
} else {
748+
// Otherwise explicitely compute the remaining ranges.
749+
remaining_ranges = other_range.subtract_from(remaining_ranges);
750+
}
757751

758-
// If the ranges that have been considered so far already cover the entire
759-
// range of values, we can return early.
760-
if remaining_ranges.is_empty() {
761-
break;
762-
}
752+
// If the ranges that have been considered so far already cover the entire
753+
// range of values, we can return early.
754+
if remaining_ranges.is_empty() {
755+
break;
763756
}
757+
}
764758

765-
// Convert the ranges back into constructors
766-
remaining_ranges.into_iter().map(IntRange).collect()
759+
// Convert the ranges back into constructors
760+
remaining_ranges.into_iter().map(IntRange).collect()
761+
}
762+
ConstantRange(..) | ConstantValue(..) => {
763+
if other_ctors.iter().any(|c| {
764+
c == self
765+
// FIXME(Nadrieril): This condition looks fishy
766+
|| IntRange::from_ctor(tcx, param_env, c).is_some()
767+
}) {
768+
vec![]
767769
} else {
768-
if other_ctors.iter().any(|c| {
769-
c == self
770-
// FIXME(Nadrieril): This condition looks fishy
771-
|| IntRange::from_ctor(tcx, param_env, c).is_some()
772-
}) {
773-
vec![]
774-
} else {
775-
vec![self.clone()]
776-
}
770+
vec![self.clone()]
777771
}
778772
}
779773
}
@@ -1233,6 +1227,10 @@ impl<'tcx> IntRange<'tcx> {
12331227
}
12341228
}
12351229

1230+
fn is_singleton(&self) -> bool {
1231+
self.range.start() == self.range.end()
1232+
}
1233+
12361234
fn should_treat_range_exhaustively(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
12371235
// Don't treat `usize`/`isize` exhaustively unless the `precise_pointer_size_matching`
12381236
// feature is enabled.
@@ -1309,15 +1307,13 @@ impl<'tcx> IntRange<'tcx> {
13091307
}
13101308

13111309
fn from_ctor(
1312-
tcx: TyCtxt<'tcx>,
1313-
param_env: ty::ParamEnv<'tcx>,
1310+
_tcx: TyCtxt<'tcx>,
1311+
_param_env: ty::ParamEnv<'tcx>,
13141312
ctor: &Constructor<'tcx>,
13151313
) -> Option<IntRange<'tcx>> {
13161314
// Floating-point ranges are permitted and we don't want
13171315
// to consider them when constructing integer ranges.
13181316
match ctor {
1319-
ConstantRange(lo, hi, ty, end, span) => Self::from_range(tcx, *lo, *hi, ty, end, *span),
1320-
ConstantValue(val, span) => Self::from_const(tcx, param_env, val, *span),
13211317
IntRange(range) => Some(range.clone()),
13221318
_ => None,
13231319
}
@@ -1736,14 +1732,23 @@ fn pat_constructor<'tcx>(
17361732
PatKind::Variant { adt_def, variant_index, .. } => {
17371733
Some(Variant(adt_def.variants[variant_index].def_id))
17381734
}
1739-
PatKind::Constant { value } => Some(ConstantValue(value, pat.span)),
1740-
PatKind::Range(PatRange { lo, hi, end }) => Some(ConstantRange(
1741-
lo.eval_bits(tcx, param_env, lo.ty),
1742-
hi.eval_bits(tcx, param_env, hi.ty),
1743-
lo.ty,
1744-
end,
1745-
pat.span,
1746-
)),
1735+
PatKind::Constant { value } => {
1736+
if let Some(int_range) = IntRange::from_const(tcx, param_env, value, pat.span) {
1737+
Some(IntRange(int_range))
1738+
} else {
1739+
Some(ConstantValue(value, pat.span))
1740+
}
1741+
}
1742+
PatKind::Range(PatRange { lo, hi, end }) => {
1743+
let ty = lo.ty;
1744+
let lo = lo.eval_bits(tcx, param_env, lo.ty);
1745+
let hi = hi.eval_bits(tcx, param_env, hi.ty);
1746+
if let Some(int_range) = IntRange::from_range(tcx, lo, hi, ty, &end, pat.span) {
1747+
Some(IntRange(int_range))
1748+
} else {
1749+
Some(ConstantRange(lo, hi, ty, end, pat.span))
1750+
}
1751+
}
17471752
PatKind::Array { .. } => match pat.ty.kind {
17481753
ty::Array(_, length) => Some(FixedLenSlice(length.eval_usize(tcx, param_env))),
17491754
_ => span_bug!(pat.span, "bad ty {:?} for array pattern", pat.ty),
@@ -1874,13 +1879,13 @@ fn split_grouped_constructors<'p, 'tcx>(
18741879

18751880
for ctor in ctors.into_iter() {
18761881
match ctor {
1877-
IntRange(..) | ConstantRange(..)
1878-
if IntRange::should_treat_range_exhaustively(tcx, ty) =>
1879-
{
1880-
// We only care about finding all the subranges within the range of the constructor
1881-
// range. Anything else is irrelevant, because it is guaranteed to result in
1882-
// `NotUseful`, which is the default case anyway, and can be ignored.
1883-
let ctor_range = IntRange::from_ctor(tcx, param_env, &ctor).unwrap();
1882+
IntRange(ctor_range) if IntRange::should_treat_range_exhaustively(tcx, ty) => {
1883+
// Fast-track if the range is trivial. In particular, don't do the overlapping
1884+
// ranges check.
1885+
if ctor_range.is_singleton() {
1886+
split_ctors.push(IntRange(ctor_range));
1887+
continue;
1888+
}
18841889

18851890
/// Represents a border between 2 integers. Because the intervals spanning borders
18861891
/// must be able to cover every integer, we need to be able to represent

0 commit comments

Comments
 (0)