1
Fork 0

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

View file

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