Inline and remove constructor_intersects_pattern().

This is a 2% instruction count win on `unicode_normalization-check-clean`.
This commit is contained in:
Nicholas Nethercote 2019-10-04 11:04:14 +10:00
parent 9a1a3b9013
commit 62ea39a1c9

View file

@ -1625,36 +1625,6 @@ fn split_grouped_constructors<'p, 'tcx>(
split_ctors
}
/// Checks whether there exists any shared value in either `ctor` or `pat` by intersecting them.
fn constructor_intersects_pattern<'p, 'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
ctor: &Constructor<'tcx>,
pat: &'p Pat<'tcx>,
) -> Option<SmallVec<[&'p Pat<'tcx>; 2]>> {
if should_treat_range_exhaustively(tcx, ctor) {
match (IntRange::from_ctor(tcx, param_env, ctor), IntRange::from_pat(tcx, param_env, pat)) {
(Some(ctor), Some(pat)) => {
ctor.intersection(&pat).map(|_| {
let (pat_lo, pat_hi) = pat.range.into_inner();
let (ctor_lo, ctor_hi) = ctor.range.into_inner();
assert!(pat_lo <= ctor_lo && ctor_hi <= pat_hi);
smallvec![]
})
}
_ => None,
}
} else {
// Fallback for non-ranges and ranges that involve floating-point numbers, which are not
// conveniently handled by `IntRange`. For these cases, the constructor may not be a range
// so intersection actually devolves into being covered by the pattern.
match constructor_covered_by_range(tcx, param_env, ctor, pat) {
Ok(true) => Some(smallvec![]),
Ok(false) | Err(ErrorReported) => None,
}
}
}
fn constructor_covered_by_range<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>,
@ -1845,9 +1815,32 @@ fn specialize<'p, 'a: 'p, 'tcx>(
PatKind::Constant { .. } |
PatKind::Range { .. } => {
// If the constructor is a:
// Single value: add a row if the pattern contains the constructor.
// Range: add a row if the constructor intersects the pattern.
constructor_intersects_pattern(cx.tcx, cx.param_env, constructor, pat)
// - Single value: add a row if the pattern contains the constructor.
// - Range: add a row if the constructor intersects the pattern.
if should_treat_range_exhaustively(cx.tcx, constructor) {
match (IntRange::from_ctor(cx.tcx, cx.param_env, constructor),
IntRange::from_pat(cx.tcx, cx.param_env, pat)) {
(Some(ctor), Some(pat)) => {
ctor.intersection(&pat).map(|_| {
let (pat_lo, pat_hi) = pat.range.into_inner();
let (ctor_lo, ctor_hi) = ctor.range.into_inner();
assert!(pat_lo <= ctor_lo && ctor_hi <= pat_hi);
smallvec![]
})
}
_ => None,
}
} else {
// Fallback for non-ranges and ranges that involve
// floating-point numbers, which are not conveniently handled
// by `IntRange`. For these cases, the constructor may not be a
// range so intersection actually devolves into being covered
// by the pattern.
match constructor_covered_by_range(cx.tcx, cx.param_env, constructor, pat) {
Ok(true) => Some(smallvec![]),
Ok(false) | Err(ErrorReported) => None,
}
}
}
PatKind::Array { ref prefix, ref slice, ref suffix } |