Rename pat_constructor
to Constructor::from_pat
This commit is contained in:
parent
ba3c419a43
commit
2de0475826
2 changed files with 63 additions and 63 deletions
|
@ -306,7 +306,7 @@
|
||||||
use self::Usefulness::*;
|
use self::Usefulness::*;
|
||||||
use self::WitnessPreference::*;
|
use self::WitnessPreference::*;
|
||||||
|
|
||||||
use super::deconstruct_pat::{pat_constructor, Constructor, Fields, MissingConstructors};
|
use super::deconstruct_pat::{Constructor, Fields, MissingConstructors};
|
||||||
use super::{Pat, PatKind};
|
use super::{Pat, PatKind};
|
||||||
use super::{PatternFoldable, PatternFolder};
|
use super::{PatternFoldable, PatternFolder};
|
||||||
|
|
||||||
|
@ -438,7 +438,7 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn head_ctor<'a>(&'a self, cx: &MatchCheckCtxt<'p, 'tcx>) -> &'a Constructor<'tcx> {
|
fn head_ctor<'a>(&'a self, cx: &MatchCheckCtxt<'p, 'tcx>) -> &'a Constructor<'tcx> {
|
||||||
self.head_ctor.get_or_init(|| pat_constructor(cx, self.head()))
|
self.head_ctor.get_or_init(|| Constructor::from_pat(cx, self.head()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn iter(&self) -> impl Iterator<Item = &Pat<'tcx>> {
|
fn iter(&self) -> impl Iterator<Item = &Pat<'tcx>> {
|
||||||
|
|
|
@ -606,6 +606,67 @@ impl<'tcx> Constructor<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Determines the constructor that the given pattern can be specialized to.
|
||||||
|
pub(super) fn from_pat<'p>(cx: &MatchCheckCtxt<'p, 'tcx>, pat: &'p Pat<'tcx>) -> Self {
|
||||||
|
match pat.kind.as_ref() {
|
||||||
|
PatKind::AscribeUserType { .. } => bug!(), // Handled by `expand_pattern`
|
||||||
|
PatKind::Binding { .. } | PatKind::Wild => Wildcard,
|
||||||
|
PatKind::Leaf { .. } | PatKind::Deref { .. } => Single,
|
||||||
|
&PatKind::Variant { adt_def, variant_index, .. } => {
|
||||||
|
Variant(adt_def.variants[variant_index].def_id)
|
||||||
|
}
|
||||||
|
PatKind::Constant { value } => {
|
||||||
|
if let Some(int_range) = IntRange::from_const(cx.tcx, cx.param_env, value, pat.span)
|
||||||
|
{
|
||||||
|
IntRange(int_range)
|
||||||
|
} else {
|
||||||
|
match pat.ty.kind() {
|
||||||
|
ty::Float(_) => FloatRange(value, value, RangeEnd::Included),
|
||||||
|
// In `expand_pattern`, we convert string literals to `&CONST` patterns with
|
||||||
|
// `CONST` a pattern of type `str`. In truth this contains a constant of type
|
||||||
|
// `&str`.
|
||||||
|
ty::Str => Str(value),
|
||||||
|
// All constants that can be structurally matched have already been expanded
|
||||||
|
// into the corresponding `Pat`s by `const_to_pat`. Constants that remain are
|
||||||
|
// opaque.
|
||||||
|
_ => Opaque,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&PatKind::Range(PatRange { lo, hi, end }) => {
|
||||||
|
let ty = lo.ty;
|
||||||
|
if let Some(int_range) = IntRange::from_range(
|
||||||
|
cx.tcx,
|
||||||
|
lo.eval_bits(cx.tcx, cx.param_env, lo.ty),
|
||||||
|
hi.eval_bits(cx.tcx, cx.param_env, hi.ty),
|
||||||
|
ty,
|
||||||
|
&end,
|
||||||
|
pat.span,
|
||||||
|
) {
|
||||||
|
IntRange(int_range)
|
||||||
|
} else {
|
||||||
|
FloatRange(lo, hi, end)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PatKind::Array { prefix, slice, suffix } | PatKind::Slice { prefix, slice, suffix } => {
|
||||||
|
let array_len = match pat.ty.kind() {
|
||||||
|
ty::Array(_, length) => Some(length.eval_usize(cx.tcx, cx.param_env)),
|
||||||
|
ty::Slice(_) => None,
|
||||||
|
_ => span_bug!(pat.span, "bad ty {:?} for slice pattern", pat.ty),
|
||||||
|
};
|
||||||
|
let prefix = prefix.len() as u64;
|
||||||
|
let suffix = suffix.len() as u64;
|
||||||
|
let kind = if slice.is_some() {
|
||||||
|
VarLen(prefix, suffix)
|
||||||
|
} else {
|
||||||
|
FixedLen(prefix + suffix)
|
||||||
|
};
|
||||||
|
Slice(Slice::new(array_len, kind))
|
||||||
|
}
|
||||||
|
PatKind::Or { .. } => bug!("Or-pattern should have been expanded earlier on."),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Some constructors (namely `Wildcard`, `IntRange` and `Slice`) actually stand for a set of actual
|
/// Some constructors (namely `Wildcard`, `IntRange` and `Slice`) actually stand for a set of actual
|
||||||
/// constructors (like variants, integers or fixed-sized slices). When specializing for these
|
/// constructors (like variants, integers or fixed-sized slices). When specializing for these
|
||||||
/// constructors, we want to be specialising for the actual underlying constructors.
|
/// constructors, we want to be specialising for the actual underlying constructors.
|
||||||
|
@ -756,67 +817,6 @@ impl<'tcx> Constructor<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determines the constructor that the given pattern can be specialized to.
|
|
||||||
/// Returns `None` in case of a catch-all, which can't be specialized.
|
|
||||||
pub(super) fn pat_constructor<'p, 'tcx>(
|
|
||||||
cx: &MatchCheckCtxt<'p, 'tcx>,
|
|
||||||
pat: &'p Pat<'tcx>,
|
|
||||||
) -> Constructor<'tcx> {
|
|
||||||
match pat.kind.as_ref() {
|
|
||||||
PatKind::AscribeUserType { .. } => bug!(), // Handled by `expand_pattern`
|
|
||||||
PatKind::Binding { .. } | PatKind::Wild => Wildcard,
|
|
||||||
PatKind::Leaf { .. } | PatKind::Deref { .. } => Single,
|
|
||||||
&PatKind::Variant { adt_def, variant_index, .. } => {
|
|
||||||
Variant(adt_def.variants[variant_index].def_id)
|
|
||||||
}
|
|
||||||
PatKind::Constant { value } => {
|
|
||||||
if let Some(int_range) = IntRange::from_const(cx.tcx, cx.param_env, value, pat.span) {
|
|
||||||
IntRange(int_range)
|
|
||||||
} else {
|
|
||||||
match pat.ty.kind() {
|
|
||||||
ty::Float(_) => FloatRange(value, value, RangeEnd::Included),
|
|
||||||
// In `expand_pattern`, we convert string literals to `&CONST` patterns with
|
|
||||||
// `CONST` a pattern of type `str`. In truth this contains a constant of type
|
|
||||||
// `&str`.
|
|
||||||
ty::Str => Str(value),
|
|
||||||
// All constants that can be structurally matched have already been expanded
|
|
||||||
// into the corresponding `Pat`s by `const_to_pat`. Constants that remain are
|
|
||||||
// opaque.
|
|
||||||
_ => Opaque,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&PatKind::Range(PatRange { lo, hi, end }) => {
|
|
||||||
let ty = lo.ty;
|
|
||||||
if let Some(int_range) = IntRange::from_range(
|
|
||||||
cx.tcx,
|
|
||||||
lo.eval_bits(cx.tcx, cx.param_env, lo.ty),
|
|
||||||
hi.eval_bits(cx.tcx, cx.param_env, hi.ty),
|
|
||||||
ty,
|
|
||||||
&end,
|
|
||||||
pat.span,
|
|
||||||
) {
|
|
||||||
IntRange(int_range)
|
|
||||||
} else {
|
|
||||||
FloatRange(lo, hi, end)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PatKind::Array { prefix, slice, suffix } | PatKind::Slice { prefix, slice, suffix } => {
|
|
||||||
let array_len = match pat.ty.kind() {
|
|
||||||
ty::Array(_, length) => Some(length.eval_usize(cx.tcx, cx.param_env)),
|
|
||||||
ty::Slice(_) => None,
|
|
||||||
_ => span_bug!(pat.span, "bad ty {:?} for slice pattern", pat.ty),
|
|
||||||
};
|
|
||||||
let prefix = prefix.len() as u64;
|
|
||||||
let suffix = suffix.len() as u64;
|
|
||||||
let kind =
|
|
||||||
if slice.is_some() { VarLen(prefix, suffix) } else { FixedLen(prefix + suffix) };
|
|
||||||
Slice(Slice::new(array_len, kind))
|
|
||||||
}
|
|
||||||
PatKind::Or { .. } => bug!("Or-pattern should have been expanded earlier on."),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This determines the set of all possible constructors of a pattern matching
|
/// This determines the set of all possible constructors of a pattern matching
|
||||||
/// values of type `left_ty`. For vectors, this would normally be an infinite set
|
/// values of type `left_ty`. For vectors, this would normally be an infinite set
|
||||||
/// but is instead bounded by the maximum fixed length of slice patterns in
|
/// but is instead bounded by the maximum fixed length of slice patterns in
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue