Introduce IntRange constructor

This commit is contained in:
Nadrieril 2019-11-15 16:39:31 +00:00
parent 1909e3f2bf
commit f93a70063c

View File

@ -590,7 +590,10 @@ enum Constructor<'tcx> {
Variant(DefId),
/// Literal values.
ConstantValue(&'tcx ty::Const<'tcx>, Span),
/// Ranges of literal values (`2..=5` and `2..5`).
/// Ranges of integer literal values (`2`, `2..=5` or `2..5`).
IntRange(IntRange<'tcx>),
// TODO: non-integer
/// Ranges of literal values (`2.0..=5.2`).
ConstantRange(u128, u128, Ty<'tcx>, RangeEnd, Span),
/// Array patterns of length `n`.
FixedLenSlice(u64),
@ -612,6 +615,7 @@ fn eq(&self, other: &Self) -> bool {
Constructor::ConstantRange(a_start, a_end, a_ty, a_range_end, _),
Constructor::ConstantRange(b_start, b_end, b_ty, b_range_end, _),
) => a_start == b_start && a_end == b_end && a_ty == b_ty && a_range_end == b_range_end,
(Constructor::IntRange(a), Constructor::IntRange(b)) => a == b,
(Constructor::FixedLenSlice(a), Constructor::FixedLenSlice(b)) => a == b,
(
Constructor::VarLenSlice(a_prefix, a_suffix),
@ -634,6 +638,7 @@ fn is_integral_range(&self) -> bool {
let ty = match self {
ConstantValue(value, _) => value.ty,
ConstantRange(_, _, ty, _, _) => ty,
IntRange(_) => return true,
_ => return false,
};
IntRange::is_integral(ty)
@ -743,7 +748,7 @@ fn subtract_ctors(
remaining_ctors
}
ConstantRange(..) | ConstantValue(..) => {
IntRange(..) | ConstantRange(..) | ConstantValue(..) => {
if let Some(self_range) = IntRange::from_ctor(tcx, param_env, self) {
let mut remaining_ranges = vec![self_range.clone()];
let other_ranges = other_ctors
@ -767,7 +772,7 @@ fn subtract_ctors(
}
// Convert the ranges back into constructors
remaining_ranges.into_iter().map(|range| range.into_ctor(tcx)).collect()
remaining_ranges.into_iter().map(IntRange).collect()
} else {
if other_ctors.iter().any(|c| {
c == self
@ -855,7 +860,7 @@ fn wildcard_subpatterns<'a>(
}
_ => bug!("bad slice pattern {:?} {:?}", self, ty),
},
ConstantValue(..) | ConstantRange(..) | NonExhaustive => vec![],
ConstantValue(..) | ConstantRange(..) | IntRange(..) | NonExhaustive => vec![],
}
}
@ -880,7 +885,7 @@ fn arity<'a>(&self, cx: &MatchCheckCtxt<'a, 'tcx>, ty: Ty<'tcx>) -> u64 {
},
FixedLenSlice(length) => *length,
VarLenSlice(prefix, suffix) => prefix + suffix,
ConstantValue(..) | ConstantRange(..) | NonExhaustive => 0,
ConstantValue(..) | ConstantRange(..) | IntRange(..) | NonExhaustive => 0,
}
}
@ -949,6 +954,10 @@ fn apply<'a>(
hi: ty::Const::from_bits(cx.tcx, hi, ty::ParamEnv::empty().and(ty)),
end,
}),
IntRange(range) => {
// TODO: do it more directly
return range.clone().into_ctor(cx.tcx).apply(cx, ty, None.into_iter());
}
NonExhaustive => PatKind::Wild,
};
@ -1145,7 +1154,14 @@ fn all_constructors<'a, 'tcx>(
pcx: PatCtxt<'tcx>,
) -> Vec<Constructor<'tcx>> {
debug!("all_constructors({:?})", pcx.ty);
let make_range = |start, end| ConstantRange(start, end, pcx.ty, RangeEnd::Included, pcx.span);
let make_range = |start, end| {
IntRange(
// `unwrap()` is ok because we know the type is an integer and the range is
// well-formed.
IntRange::from_range(cx.tcx, start, end, pcx.ty, &RangeEnd::Included, pcx.span)
.unwrap(),
)
};
match pcx.ty.kind {
ty::Bool => [true, false]
.iter()
@ -1356,6 +1372,7 @@ fn from_ctor(
match ctor {
ConstantRange(lo, hi, ty, end, span) => Self::from_range(tcx, *lo, *hi, ty, end, *span),
ConstantValue(val, span) => Self::from_const(tcx, param_env, val, *span),
IntRange(range) => Some(range.clone()),
_ => None,
}
}
@ -1381,6 +1398,7 @@ fn signed_bias(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> u128 {
}
/// Converts an `IntRange` to a `ConstantValue` or inclusive `ConstantRange`.
/// TODO: Deprecated
fn into_ctor(self, tcx: TyCtxt<'tcx>) -> Constructor<'tcx> {
let bias = IntRange::signed_bias(tcx, self.ty);
let (lo, hi) = self.range.into_inner();
@ -1889,7 +1907,9 @@ fn split_grouped_constructors<'p, 'tcx>(
for ctor in ctors.into_iter() {
match ctor {
ConstantRange(..) if IntRange::should_treat_range_exhaustively(tcx, ty) => {
IntRange(..) | ConstantRange(..)
if IntRange::should_treat_range_exhaustively(tcx, ty) =>
{
// We only care about finding all the subranges within the range of the constructor
// range. Anything else is irrelevant, because it is guaranteed to result in
// `NotUseful`, which is the default case anyway, and can be ignored.
@ -1968,7 +1988,7 @@ fn range_borders(r: IntRange<'_>) -> impl Iterator<Item = Border> {
}
(Border::AfterMax, _) => None,
})
.map(|range| range.into_ctor(tcx)),
.map(IntRange),
);
}
VarLenSlice(self_prefix, self_suffix) => {