Skip to content

Commit 94227f5

Browse files
committed
Store Const in ConstantRange
This makes the conversions from/to Const better localized. In particular, eval_bits only happens in IntRange::from_ctor.
1 parent f5d833f commit 94227f5

File tree

1 file changed

+35
-48
lines changed

1 file changed

+35
-48
lines changed

src/librustc_mir/hair/pattern/_match.rs

Lines changed: 35 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,7 @@ enum Constructor<'tcx> {
581581

582582
// Meta-constructors
583583
/// Ranges of literal values (`2..=5` and `2..5`).
584-
ConstantRange(u128, u128, Ty<'tcx>, RangeEnd),
584+
ConstantRange(&'tcx ty::Const<'tcx>, &'tcx ty::Const<'tcx>, RangeEnd),
585585
/// Slice patterns. Captures any array constructor of length >= i+j.
586586
VarLenSlice(u64, u64),
587587
/// Wildcard metaconstructor. Captures all possible constructors for a given type.
@@ -1151,7 +1151,7 @@ impl<'tcx> Constructor<'tcx> {
11511151
pats: impl IntoIterator<Item = Pat<'tcx>>,
11521152
) -> SmallVec<[Pat<'tcx>; 1]> {
11531153
let mut pats = pats.into_iter();
1154-
let pat = match self {
1154+
let pat = match *self {
11551155
Single | Variant(_) => match ty.kind {
11561156
ty::Adt(..) | ty::Tuple(..) => {
11571157
let pats = pats
@@ -1183,7 +1183,7 @@ impl<'tcx> Constructor<'tcx> {
11831183
VarLenSlice(prefix_len, _suffix_len) => match ty.kind {
11841184
ty::Slice(ty) | ty::Array(ty, _) => {
11851185
if cx.tcx.features().slice_patterns {
1186-
let prefix = pats.by_ref().take(*prefix_len as usize).collect();
1186+
let prefix = pats.by_ref().take(prefix_len as usize).collect();
11871187
let suffix = pats.collect();
11881188
let wild = Pat { ty, span: DUMMY_SP, kind: Box::new(PatKind::Wild) };
11891189
PatKind::Slice { prefix, slice: Some(wild), suffix }
@@ -1199,13 +1199,9 @@ impl<'tcx> Constructor<'tcx> {
11991199
_ => bug!("bad slice pattern {:?} {:?}", self, ty),
12001200
},
12011201
ConstantValue(value) => PatKind::Constant { value },
1202-
ConstantRange(lo, hi, ty, end) => PatKind::Range(PatRange {
1203-
lo: ty::Const::from_bits(cx.tcx, *lo, ty::ParamEnv::empty().and(ty)),
1204-
hi: ty::Const::from_bits(cx.tcx, *hi, ty::ParamEnv::empty().and(ty)),
1205-
end: *end,
1206-
}),
1202+
ConstantRange(lo, hi, end) => PatKind::Range(PatRange { lo, hi, end }),
12071203
Wildcard => PatKind::Wild,
1208-
MissingConstructors(missing_ctors) => {
1204+
MissingConstructors(ref missing_ctors) => {
12091205
// Construct for each missing constructor a "wildcard" version of this
12101206
// constructor, that matches everything that can be built with
12111207
// it. For example, if `ctor` is a `Constructor::Variant` for
@@ -1394,32 +1390,28 @@ fn all_constructors<'a, 'tcx>(
13941390
.map(|v| Variant(v.def_id))
13951391
.collect(),
13961392
ty::Char => {
1393+
let param_env = ty::ParamEnv::empty().and(cx.tcx.types.char);
1394+
let to_const = |x| ty::Const::from_bits(cx.tcx, x as u128, param_env);
13971395
vec![
13981396
// The valid Unicode Scalar Value ranges.
1399-
ConstantRange(
1400-
'\u{0000}' as u128,
1401-
'\u{D7FF}' as u128,
1402-
cx.tcx.types.char,
1403-
RangeEnd::Included,
1404-
),
1405-
ConstantRange(
1406-
'\u{E000}' as u128,
1407-
'\u{10FFFF}' as u128,
1408-
cx.tcx.types.char,
1409-
RangeEnd::Included,
1410-
),
1397+
ConstantRange(to_const('\u{0000}'), to_const('\u{D7FF}'), RangeEnd::Included),
1398+
ConstantRange(to_const('\u{E000}'), to_const('\u{10FFFF}'), RangeEnd::Included),
14111399
]
14121400
}
14131401
ty::Int(ity) => {
1402+
let param_env = ty::ParamEnv::empty().and(ty);
1403+
let to_const = |x| ty::Const::from_bits(cx.tcx, x, param_env);
14141404
let bits = Integer::from_attr(&cx.tcx, SignedInt(ity)).size().bits() as u128;
14151405
let min = 1u128 << (bits - 1);
14161406
let max = min - 1;
1417-
vec![ConstantRange(min, max, ty, RangeEnd::Included)]
1407+
vec![ConstantRange(to_const(min), to_const(max), RangeEnd::Included)]
14181408
}
14191409
ty::Uint(uty) => {
1410+
let param_env = ty::ParamEnv::empty().and(ty);
1411+
let to_const = |x| ty::Const::from_bits(cx.tcx, x, param_env);
14201412
let size = Integer::from_attr(&cx.tcx, UnsignedInt(uty)).size();
14211413
let max = truncate(u128::max_value(), size);
1422-
vec![ConstantRange(0, max, ty, RangeEnd::Included)]
1414+
vec![ConstantRange(to_const(0), to_const(max), RangeEnd::Included)]
14231415
}
14241416
_ => {
14251417
if cx.is_uninhabited(ty) {
@@ -1501,11 +1493,14 @@ impl<'tcx> IntRange<'tcx> {
15011493
#[inline]
15021494
fn from_range(
15031495
tcx: TyCtxt<'tcx>,
1504-
lo: u128,
1505-
hi: u128,
1506-
ty: Ty<'tcx>,
1496+
param_env: ty::ParamEnv<'tcx>,
1497+
lo: &Const<'tcx>,
1498+
hi: &Const<'tcx>,
15071499
end: &RangeEnd,
15081500
) -> Option<IntRange<'tcx>> {
1501+
let ty = lo.ty;
1502+
let lo = lo.eval_bits(tcx, param_env, lo.ty);
1503+
let hi = hi.eval_bits(tcx, param_env, hi.ty);
15091504
if Self::is_integral(ty) {
15101505
// Perform a shift if the underlying types are signed,
15111506
// which makes the interval arithmetic simpler.
@@ -1531,7 +1526,7 @@ impl<'tcx> IntRange<'tcx> {
15311526
// Floating-point ranges are permitted and we don't want
15321527
// to consider them when constructing integer ranges.
15331528
match ctor {
1534-
ConstantRange(lo, hi, ty, end) => Self::from_range(tcx, *lo, *hi, ty, end),
1529+
ConstantRange(lo, hi, end) => Self::from_range(tcx, param_env, lo, hi, end),
15351530
ConstantValue(val) => Self::from_const(tcx, param_env, val),
15361531
_ => None,
15371532
}
@@ -1560,7 +1555,9 @@ impl<'tcx> IntRange<'tcx> {
15601555
let ty = ty::ParamEnv::empty().and(ty);
15611556
ConstantValue(ty::Const::from_bits(tcx, lo ^ bias, ty))
15621557
} else {
1563-
ConstantRange(lo ^ bias, hi ^ bias, ty, RangeEnd::Included)
1558+
let param_env = ty::ParamEnv::empty().and(ty);
1559+
let to_const = |x| ty::Const::from_bits(tcx, x, param_env);
1560+
ConstantRange(to_const(lo ^ bias), to_const(hi ^ bias), RangeEnd::Included)
15641561
}
15651562
}
15661563

@@ -1811,12 +1808,7 @@ fn pat_constructors<'tcx>(
18111808
smallvec![Variant(adt_def.variants[variant_index].def_id)]
18121809
}
18131810
PatKind::Constant { value } => smallvec![ConstantValue(value)],
1814-
PatKind::Range(PatRange { lo, hi, end }) => smallvec![ConstantRange(
1815-
lo.eval_bits(tcx, param_env, lo.ty),
1816-
hi.eval_bits(tcx, param_env, hi.ty),
1817-
lo.ty,
1818-
end,
1819-
)],
1811+
PatKind::Range(PatRange { lo, hi, end }) => smallvec![ConstantRange(lo, hi, end)],
18201812
PatKind::Array { .. } => match ty.kind {
18211813
ty::Array(_, length) => smallvec![FixedLenSlice(length.eval_usize(tcx, param_env))],
18221814
_ => span_bug!(pat.span, "bad ty {:?} for array pattern", ty),
@@ -1901,7 +1893,7 @@ fn slice_pat_covered_by_const<'tcx>(
19011893
fn should_treat_range_exhaustively(tcx: TyCtxt<'tcx>, ctor: &Constructor<'tcx>) -> bool {
19021894
let ty = match ctor {
19031895
ConstantValue(value) => value.ty,
1904-
ConstantRange(_, _, ty, _) => ty,
1896+
ConstantRange(lo, _, _) => lo.ty,
19051897
_ => return false,
19061898
};
19071899
if let ty::Char | ty::Int(_) | ty::Uint(_) = ty.kind {
@@ -1921,12 +1913,7 @@ fn constructor_intersects_pattern<'p, 'tcx>(
19211913
if should_treat_range_exhaustively(tcx, ctor) {
19221914
let range = match *pat.kind {
19231915
PatKind::Constant { value } => ConstantValue(value),
1924-
PatKind::Range(PatRange { lo, hi, end }) => ConstantRange(
1925-
lo.eval_bits(tcx, param_env, lo.ty),
1926-
hi.eval_bits(tcx, param_env, hi.ty),
1927-
lo.ty,
1928-
end,
1929-
),
1916+
PatKind::Range(PatRange { lo, hi, end }) => ConstantRange(lo, hi, end),
19301917
_ => bug!("`constructor_intersects_pattern` called with {:?}", pat),
19311918
};
19321919

@@ -1942,11 +1929,12 @@ fn constructor_intersects_pattern<'p, 'tcx>(
19421929
// Fallback for non-ranges and ranges that involve floating-point numbers, which are not
19431930
// conveniently handled by `IntRange`. For these cases, the constructor may not be a range
19441931
// so intersection actually devolves into being covered by the pattern.
1945-
let (from, to, end, ty) = match *pat.kind {
1946-
PatKind::Constant { value } => (value, value, RangeEnd::Included, value.ty),
1947-
PatKind::Range(PatRange { lo, hi, end }) => (lo, hi, end, lo.ty),
1932+
let (from, to, end) = match *pat.kind {
1933+
PatKind::Constant { value } => (value, value, RangeEnd::Included),
1934+
PatKind::Range(PatRange { lo, hi, end }) => (lo, hi, end),
19481935
_ => bug!("`constructor_intersects_pattern` called with {:?}", pat),
19491936
};
1937+
let ty = from.ty;
19501938
trace!("constructor_intersects_pattern {:#?}, {:#?}, {:#?}, {}", ctor, from, to, ty);
19511939
let cmp_from = |c_from| compare_const_vals(tcx, c_from, from, param_env, ty);
19521940
let cmp_to = |c_to| compare_const_vals(tcx, c_to, to, param_env, ty);
@@ -1958,10 +1946,9 @@ fn constructor_intersects_pattern<'p, 'tcx>(
19581946
(to == Ordering::Less) || (end == RangeEnd::Included && to == Ordering::Equal);
19591947
(from != Ordering::Less) && end
19601948
}
1961-
ConstantRange(from, to, ty, range_end) => {
1962-
let to = cmp_to(ty::Const::from_bits(tcx, to, ty::ParamEnv::empty().and(ty)))?;
1963-
let from =
1964-
cmp_from(ty::Const::from_bits(tcx, from, ty::ParamEnv::empty().and(ty)))?;
1949+
ConstantRange(from, to, range_end) => {
1950+
let to = cmp_to(to)?;
1951+
let from = cmp_from(from)?;
19651952
let end = (to == Ordering::Less) || (end == range_end && to == Ordering::Equal);
19661953
(from != Ordering::Less) && end
19671954
}

0 commit comments

Comments
 (0)