Store pattern arity in DeconstructedPat

Right now this is just `self.fields.len()` but that'll change in the
next commit. `arity` will be useful for the `Debug` impl.
This commit is contained in:
Nadrieril 2024-02-29 23:34:52 +01:00
parent cd81f5b27e
commit c1e68860d0
3 changed files with 36 additions and 7 deletions

View File

@ -423,7 +423,7 @@ pub enum SliceKind {
}
impl SliceKind {
fn arity(self) -> usize {
pub fn arity(self) -> usize {
match self {
FixedLen(length) => length,
VarLen(prefix, suffix) => prefix + suffix,
@ -462,7 +462,7 @@ impl Slice {
Slice { array_len, kind }
}
pub(crate) fn arity(self) -> usize {
pub fn arity(self) -> usize {
self.kind.arity()
}

View File

@ -26,6 +26,10 @@ impl PatId {
pub struct DeconstructedPat<Cx: TypeCx> {
ctor: Constructor<Cx>,
fields: Vec<DeconstructedPat<Cx>>,
/// The number of fields in this pattern. E.g. if the pattern is `SomeStruct { field12: true, ..
/// }` this would be the total number of fields of the struct.
/// This is also the same as `self.ctor.arity(self.ty)`.
arity: usize,
ty: Cx::Ty,
/// Extra data to store in a pattern. `None` if the pattern is a wildcard that does not
/// correspond to a user-supplied pattern.
@ -36,16 +40,24 @@ pub struct DeconstructedPat<Cx: TypeCx> {
impl<Cx: TypeCx> DeconstructedPat<Cx> {
pub fn wildcard(ty: Cx::Ty) -> Self {
DeconstructedPat { ctor: Wildcard, fields: Vec::new(), ty, data: None, uid: PatId::new() }
DeconstructedPat {
ctor: Wildcard,
fields: Vec::new(),
arity: 0,
ty,
data: None,
uid: PatId::new(),
}
}
pub fn new(
ctor: Constructor<Cx>,
fields: Vec<DeconstructedPat<Cx>>,
arity: usize,
ty: Cx::Ty,
data: Cx::PatData,
) -> Self {
DeconstructedPat { ctor, fields, ty, data: Some(data), uid: PatId::new() }
DeconstructedPat { ctor, fields, arity, ty, data: Some(data), uid: PatId::new() }
}
pub(crate) fn is_or_pat(&self) -> bool {

View File

@ -445,6 +445,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
let cx = self;
let ty = cx.reveal_opaque_ty(pat.ty);
let ctor;
let arity;
let mut fields: Vec<_>;
match &pat.kind {
PatKind::AscribeUserType { subpattern, .. }
@ -453,9 +454,11 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
PatKind::Binding { subpattern: None, .. } | PatKind::Wild => {
ctor = Wildcard;
fields = vec![];
arity = 0;
}
PatKind::Deref { subpattern } => {
fields = vec![self.lower_pat(subpattern)];
arity = 1;
ctor = match ty.kind() {
// This is a box pattern.
ty::Adt(adt, ..) if adt.is_box() => Struct,
@ -467,6 +470,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
match ty.kind() {
ty::Tuple(fs) => {
ctor = Struct;
arity = fs.len();
fields = fs
.iter()
.map(|ty| cx.reveal_opaque_ty(ty))
@ -497,6 +501,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
};
ctor = Struct;
fields = vec![pat];
arity = 1;
}
ty::Adt(adt, _) => {
ctor = match pat.kind {
@ -507,6 +512,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
};
let variant =
&adt.variant(RustcMatchCheckCtxt::variant_index_for_adt(&ctor, *adt));
arity = variant.fields.len();
fields = cx
.variant_sub_tys(ty, variant)
.map(|(_, ty)| DeconstructedPat::wildcard(ty))
@ -526,6 +532,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
None => Opaque(OpaqueId::new()),
};
fields = vec![];
arity = 0;
}
ty::Char | ty::Int(_) | ty::Uint(_) => {
ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
@ -542,6 +549,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
None => Opaque(OpaqueId::new()),
};
fields = vec![];
arity = 0;
}
ty::Float(ty::FloatTy::F32) => {
ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
@ -553,6 +561,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
None => Opaque(OpaqueId::new()),
};
fields = vec![];
arity = 0;
}
ty::Float(ty::FloatTy::F64) => {
ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
@ -564,6 +573,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
None => Opaque(OpaqueId::new()),
};
fields = vec![];
arity = 0;
}
ty::Ref(_, t, _) if t.is_str() => {
// We want a `&str` constant to behave like a `Deref` pattern, to be compatible
@ -574,9 +584,10 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
// subfields.
// Note: `t` is `str`, not `&str`.
let ty = self.reveal_opaque_ty(*t);
let subpattern = DeconstructedPat::new(Str(*value), Vec::new(), ty, pat);
let subpattern = DeconstructedPat::new(Str(*value), Vec::new(), 0, ty, pat);
ctor = Ref;
fields = vec![subpattern]
fields = vec![subpattern];
arity = 1;
}
// All constants that can be structurally matched have already been expanded
// into the corresponding `Pat`s by `const_to_pat`. Constants that remain are
@ -584,6 +595,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
_ => {
ctor = Opaque(OpaqueId::new());
fields = vec![];
arity = 0;
}
}
}
@ -623,6 +635,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
_ => bug!("invalid type for range pattern: {}", ty.inner()),
};
fields = vec![];
arity = 0;
}
PatKind::Array { prefix, slice, suffix } | PatKind::Slice { prefix, slice, suffix } => {
let array_len = match ty.kind() {
@ -639,11 +652,13 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
};
ctor = Slice(Slice::new(array_len, kind));
fields = prefix.iter().chain(suffix.iter()).map(|p| self.lower_pat(&*p)).collect();
arity = kind.arity();
}
PatKind::Or { .. } => {
ctor = Or;
let pats = expand_or_pat(pat);
fields = pats.into_iter().map(|p| self.lower_pat(p)).collect();
arity = fields.len();
}
PatKind::Never => {
// A never pattern matches all the values of its type (namely none). Moreover it
@ -651,13 +666,15 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
// `Result<!, !>` which has other constructors. Hence we lower it as a wildcard.
ctor = Wildcard;
fields = vec![];
arity = 0;
}
PatKind::Error(_) => {
ctor = Opaque(OpaqueId::new());
fields = vec![];
arity = 0;
}
}
DeconstructedPat::new(ctor, fields, ty, pat)
DeconstructedPat::new(ctor, fields, arity, ty, pat)
}
/// Convert back to a `thir::PatRangeBoundary` for diagnostic purposes.