From b45458124ee662ac2746e091f28c3b70b95f7ef2 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Mon, 23 Sep 2019 17:36:42 +0200 Subject: [PATCH] Extract constructor application as a Constructor method --- src/librustc_mir/hair/pattern/_match.rs | 106 ++++++++++++++---------- 1 file changed, 64 insertions(+), 42 deletions(-) diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index a87965979e01..093df57087cb 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -674,6 +674,67 @@ impl<'tcx> Constructor<'tcx> { _ => 0, } } + + /// Apply a constructor to a list of patterns, yielding a new pattern. `pats` + /// must have as many elements as this constructor's arity. + /// + /// Examples: + /// self: Single + /// ty: tuple of 3 elements + /// pats: [10, 20, _] => (10, 20, _) + /// + /// self: Option::Some + /// ty: Option + /// pats: [false] => Some(false) + fn apply<'a>( + &self, + cx: &MatchCheckCtxt<'a, 'tcx>, + ty: Ty<'tcx>, + pats: impl IntoIterator>, + ) -> Pat<'tcx> { + let mut pats = pats.into_iter(); + let pat = match ty.kind { + ty::Adt(..) | ty::Tuple(..) => { + let pats = pats + .enumerate() + .map(|(i, p)| FieldPat { field: Field::new(i), pattern: p }) + .collect(); + + if let ty::Adt(adt, substs) = ty.kind { + if adt.is_enum() { + PatKind::Variant { + adt_def: adt, + substs, + variant_index: self.variant_index_for_adt(cx, adt), + subpatterns: pats, + } + } else { + PatKind::Leaf { subpatterns: pats } + } + } else { + PatKind::Leaf { subpatterns: pats } + } + } + + ty::Ref(..) => PatKind::Deref { subpattern: pats.nth(0).unwrap() }, + + ty::Slice(_) | ty::Array(..) => { + PatKind::Slice { prefix: pats.collect(), slice: None, suffix: vec![] } + } + + _ => match *self { + ConstantValue(value, _) => PatKind::Constant { value }, + ConstantRange(lo, hi, ty, end, _) => PatKind::Range(PatRange { + lo: ty::Const::from_bits(cx.tcx, lo, ty::ParamEnv::empty().and(ty)), + hi: ty::Const::from_bits(cx.tcx, hi, ty::ParamEnv::empty().and(ty)), + end, + }), + _ => PatKind::Wild, + }, + }; + + Pat { ty, span: DUMMY_SP, kind: Box::new(pat) } + } } #[derive(Clone, Debug)] @@ -778,50 +839,11 @@ impl<'tcx> Witness<'tcx> { let arity = ctor.arity(cx, ty); let pat = { let len = self.0.len() as u64; - let mut pats = self.0.drain((len - arity) as usize..).rev(); - - match ty.kind { - ty::Adt(..) | ty::Tuple(..) => { - let pats = pats - .enumerate() - .map(|(i, p)| FieldPat { field: Field::new(i), pattern: p }) - .collect(); - - if let ty::Adt(adt, substs) = ty.kind { - if adt.is_enum() { - PatKind::Variant { - adt_def: adt, - substs, - variant_index: ctor.variant_index_for_adt(cx, adt), - subpatterns: pats, - } - } else { - PatKind::Leaf { subpatterns: pats } - } - } else { - PatKind::Leaf { subpatterns: pats } - } - } - - ty::Ref(..) => PatKind::Deref { subpattern: pats.nth(0).unwrap() }, - - ty::Slice(_) | ty::Array(..) => { - PatKind::Slice { prefix: pats.collect(), slice: None, suffix: vec![] } - } - - _ => match *ctor { - ConstantValue(value, _) => PatKind::Constant { value }, - ConstantRange(lo, hi, ty, end, _) => PatKind::Range(PatRange { - lo: ty::Const::from_bits(cx.tcx, lo, ty::ParamEnv::empty().and(ty)), - hi: ty::Const::from_bits(cx.tcx, hi, ty::ParamEnv::empty().and(ty)), - end, - }), - _ => PatKind::Wild, - }, - } + let pats = self.0.drain((len - arity) as usize..).rev(); + ctor.apply(cx, ty, pats) }; - self.0.push(Pat { ty, span: DUMMY_SP, kind: Box::new(pat) }); + self.0.push(pat); self }