Skip to content

Commit c1e6886

Browse files
committed
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.
1 parent cd81f5b commit c1e6886

File tree

3 files changed

+36
-7
lines changed

3 files changed

+36
-7
lines changed

compiler/rustc_pattern_analysis/src/constructor.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ pub enum SliceKind {
423423
}
424424

425425
impl SliceKind {
426-
fn arity(self) -> usize {
426+
pub fn arity(self) -> usize {
427427
match self {
428428
FixedLen(length) => length,
429429
VarLen(prefix, suffix) => prefix + suffix,
@@ -462,7 +462,7 @@ impl Slice {
462462
Slice { array_len, kind }
463463
}
464464

465-
pub(crate) fn arity(self) -> usize {
465+
pub fn arity(self) -> usize {
466466
self.kind.arity()
467467
}
468468

compiler/rustc_pattern_analysis/src/pat.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ impl PatId {
2626
pub struct DeconstructedPat<Cx: TypeCx> {
2727
ctor: Constructor<Cx>,
2828
fields: Vec<DeconstructedPat<Cx>>,
29+
/// The number of fields in this pattern. E.g. if the pattern is `SomeStruct { field12: true, ..
30+
/// }` this would be the total number of fields of the struct.
31+
/// This is also the same as `self.ctor.arity(self.ty)`.
32+
arity: usize,
2933
ty: Cx::Ty,
3034
/// Extra data to store in a pattern. `None` if the pattern is a wildcard that does not
3135
/// correspond to a user-supplied pattern.
@@ -36,16 +40,24 @@ pub struct DeconstructedPat<Cx: TypeCx> {
3640

3741
impl<Cx: TypeCx> DeconstructedPat<Cx> {
3842
pub fn wildcard(ty: Cx::Ty) -> Self {
39-
DeconstructedPat { ctor: Wildcard, fields: Vec::new(), ty, data: None, uid: PatId::new() }
43+
DeconstructedPat {
44+
ctor: Wildcard,
45+
fields: Vec::new(),
46+
arity: 0,
47+
ty,
48+
data: None,
49+
uid: PatId::new(),
50+
}
4051
}
4152

4253
pub fn new(
4354
ctor: Constructor<Cx>,
4455
fields: Vec<DeconstructedPat<Cx>>,
56+
arity: usize,
4557
ty: Cx::Ty,
4658
data: Cx::PatData,
4759
) -> Self {
48-
DeconstructedPat { ctor, fields, ty, data: Some(data), uid: PatId::new() }
60+
DeconstructedPat { ctor, fields, arity, ty, data: Some(data), uid: PatId::new() }
4961
}
5062

5163
pub(crate) fn is_or_pat(&self) -> bool {

compiler/rustc_pattern_analysis/src/rustc.rs

+20-3
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
445445
let cx = self;
446446
let ty = cx.reveal_opaque_ty(pat.ty);
447447
let ctor;
448+
let arity;
448449
let mut fields: Vec<_>;
449450
match &pat.kind {
450451
PatKind::AscribeUserType { subpattern, .. }
@@ -453,9 +454,11 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
453454
PatKind::Binding { subpattern: None, .. } | PatKind::Wild => {
454455
ctor = Wildcard;
455456
fields = vec![];
457+
arity = 0;
456458
}
457459
PatKind::Deref { subpattern } => {
458460
fields = vec![self.lower_pat(subpattern)];
461+
arity = 1;
459462
ctor = match ty.kind() {
460463
// This is a box pattern.
461464
ty::Adt(adt, ..) if adt.is_box() => Struct,
@@ -467,6 +470,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
467470
match ty.kind() {
468471
ty::Tuple(fs) => {
469472
ctor = Struct;
473+
arity = fs.len();
470474
fields = fs
471475
.iter()
472476
.map(|ty| cx.reveal_opaque_ty(ty))
@@ -497,6 +501,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
497501
};
498502
ctor = Struct;
499503
fields = vec![pat];
504+
arity = 1;
500505
}
501506
ty::Adt(adt, _) => {
502507
ctor = match pat.kind {
@@ -507,6 +512,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
507512
};
508513
let variant =
509514
&adt.variant(RustcMatchCheckCtxt::variant_index_for_adt(&ctor, *adt));
515+
arity = variant.fields.len();
510516
fields = cx
511517
.variant_sub_tys(ty, variant)
512518
.map(|(_, ty)| DeconstructedPat::wildcard(ty))
@@ -526,6 +532,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
526532
None => Opaque(OpaqueId::new()),
527533
};
528534
fields = vec![];
535+
arity = 0;
529536
}
530537
ty::Char | ty::Int(_) | ty::Uint(_) => {
531538
ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
@@ -542,6 +549,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
542549
None => Opaque(OpaqueId::new()),
543550
};
544551
fields = vec![];
552+
arity = 0;
545553
}
546554
ty::Float(ty::FloatTy::F32) => {
547555
ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
@@ -553,6 +561,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
553561
None => Opaque(OpaqueId::new()),
554562
};
555563
fields = vec![];
564+
arity = 0;
556565
}
557566
ty::Float(ty::FloatTy::F64) => {
558567
ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
@@ -564,6 +573,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
564573
None => Opaque(OpaqueId::new()),
565574
};
566575
fields = vec![];
576+
arity = 0;
567577
}
568578
ty::Ref(_, t, _) if t.is_str() => {
569579
// We want a `&str` constant to behave like a `Deref` pattern, to be compatible
@@ -574,16 +584,18 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
574584
// subfields.
575585
// Note: `t` is `str`, not `&str`.
576586
let ty = self.reveal_opaque_ty(*t);
577-
let subpattern = DeconstructedPat::new(Str(*value), Vec::new(), ty, pat);
587+
let subpattern = DeconstructedPat::new(Str(*value), Vec::new(), 0, ty, pat);
578588
ctor = Ref;
579-
fields = vec![subpattern]
589+
fields = vec![subpattern];
590+
arity = 1;
580591
}
581592
// All constants that can be structurally matched have already been expanded
582593
// into the corresponding `Pat`s by `const_to_pat`. Constants that remain are
583594
// opaque.
584595
_ => {
585596
ctor = Opaque(OpaqueId::new());
586597
fields = vec![];
598+
arity = 0;
587599
}
588600
}
589601
}
@@ -623,6 +635,7 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
623635
_ => bug!("invalid type for range pattern: {}", ty.inner()),
624636
};
625637
fields = vec![];
638+
arity = 0;
626639
}
627640
PatKind::Array { prefix, slice, suffix } | PatKind::Slice { prefix, slice, suffix } => {
628641
let array_len = match ty.kind() {
@@ -639,25 +652,29 @@ impl<'p, 'tcx: 'p> RustcMatchCheckCtxt<'p, 'tcx> {
639652
};
640653
ctor = Slice(Slice::new(array_len, kind));
641654
fields = prefix.iter().chain(suffix.iter()).map(|p| self.lower_pat(&*p)).collect();
655+
arity = kind.arity();
642656
}
643657
PatKind::Or { .. } => {
644658
ctor = Or;
645659
let pats = expand_or_pat(pat);
646660
fields = pats.into_iter().map(|p| self.lower_pat(p)).collect();
661+
arity = fields.len();
647662
}
648663
PatKind::Never => {
649664
// A never pattern matches all the values of its type (namely none). Moreover it
650665
// must be compatible with other constructors, since we can use `!` on a type like
651666
// `Result<!, !>` which has other constructors. Hence we lower it as a wildcard.
652667
ctor = Wildcard;
653668
fields = vec![];
669+
arity = 0;
654670
}
655671
PatKind::Error(_) => {
656672
ctor = Opaque(OpaqueId::new());
657673
fields = vec![];
674+
arity = 0;
658675
}
659676
}
660-
DeconstructedPat::new(ctor, fields, ty, pat)
677+
DeconstructedPat::new(ctor, fields, arity, ty, pat)
661678
}
662679

663680
/// Convert back to a `thir::PatRangeBoundary` for diagnostic purposes.

0 commit comments

Comments
 (0)