From 76dea86df44c172ba315f2938693f4ca1bd03b7c Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Sat, 9 May 2020 11:32:54 +0100 Subject: [PATCH] Factor out a struct that holds subfields of a pattern --- src/librustc_mir_build/hair/pattern/_match.rs | 53 +++++++++++++++---- 1 file changed, 43 insertions(+), 10 deletions(-) diff --git a/src/librustc_mir_build/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs index b2b7959f0ba..688af15bd74 100644 --- a/src/librustc_mir_build/hair/pattern/_match.rs +++ b/src/librustc_mir_build/hair/pattern/_match.rs @@ -441,7 +441,7 @@ fn specialize_constructor( &self, cx: &mut MatchCheckCtxt<'p, 'tcx>, constructor: &Constructor<'tcx>, - ctor_wild_subpatterns: &'p [Pat<'tcx>], + ctor_wild_subpatterns: &Fields<'p, 'tcx>, ) -> Option> { let new_heads = specialize_one_pattern(cx, self.head(), constructor, ctor_wild_subpatterns); new_heads.map(|mut new_head| { @@ -503,7 +503,7 @@ fn specialize_constructor( &self, cx: &mut MatchCheckCtxt<'p, 'tcx>, constructor: &Constructor<'tcx>, - ctor_wild_subpatterns: &'p [Pat<'tcx>], + ctor_wild_subpatterns: &Fields<'p, 'tcx>, ) -> Matrix<'p, 'tcx> { self.0 .iter() @@ -722,10 +722,12 @@ fn arity(self) -> u64 { } } +/// A value can be decomposed into a constructor applied to some fields. This struct represents +/// the constructor. See also `Fields`. #[derive(Clone, Debug, PartialEq)] enum Constructor<'tcx> { - /// The constructor of all patterns that don't vary by constructor, - /// e.g., struct patterns and fixed-length arrays. + /// The constructor for patterns that have a single constructor, like tuples, struct patterns + /// and fixed-length arrays. Single, /// Enum variants. Variant(DefId), @@ -1027,6 +1029,38 @@ fn apply_wildcards<'a>(&self, cx: &MatchCheckCtxt<'a, 'tcx>, ty: Ty<'tcx>) -> Pa } } +/// A value can be decomposed into a constructor applied to some fields. This struct represents +/// those fields, generalized to allow patterns in each field. See also `Constructor`. +#[derive(Debug, Clone)] +enum Fields<'p, 'tcx> { + Slice(&'p [Pat<'tcx>]), +} + +impl<'p, 'tcx> Fields<'p, 'tcx> { + /// Creates a new list of wildcard fields for a given constructor. + fn wildcards( + cx: &MatchCheckCtxt<'p, 'tcx>, + constructor: &Constructor<'tcx>, + ty: Ty<'tcx>, + ) -> Self { + debug!("Fields::wildcards({:#?}, {:?})", constructor, ty); + let pats = cx.pattern_arena.alloc_from_iter(constructor.wildcard_subpatterns(cx, ty)); + Fields::Slice(pats) + } + + fn len(&self) -> usize { + match self { + Fields::Slice(pats) => pats.len(), + } + } + + fn iter<'a>(&'a self) -> impl Iterator> + Captures<'a> { + match self { + Fields::Slice(pats) => pats.iter(), + } + } +} + #[derive(Clone, Debug)] crate enum Usefulness<'tcx, 'p> { /// Carries a list of unreachable subpatterns. Used only in the presence of or-patterns. @@ -1823,10 +1857,9 @@ fn is_useful_specialized<'p, 'tcx>( ) -> Usefulness<'tcx, 'p> { debug!("is_useful_specialized({:#?}, {:#?}, {:?})", v, ctor, lty); - let ctor_wild_subpatterns = - cx.pattern_arena.alloc_from_iter(ctor.wildcard_subpatterns(cx, lty)); - let matrix = matrix.specialize_constructor(cx, &ctor, ctor_wild_subpatterns); - v.specialize_constructor(cx, &ctor, ctor_wild_subpatterns) + let ctor_wild_subpatterns = Fields::wildcards(cx, &ctor, lty); + let matrix = matrix.specialize_constructor(cx, &ctor, &ctor_wild_subpatterns); + v.specialize_constructor(cx, &ctor, &ctor_wild_subpatterns) .map(|v| is_useful(cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false)) .map(|u| u.apply_constructor(cx, &ctor, lty)) .unwrap_or(NotUseful) @@ -2295,7 +2328,7 @@ fn constructor_covered_by_range<'tcx>( fn patterns_for_variant<'p, 'tcx>( cx: &mut MatchCheckCtxt<'p, 'tcx>, subpatterns: &'p [FieldPat<'tcx>], - ctor_wild_subpatterns: &'p [Pat<'tcx>], + ctor_wild_subpatterns: &Fields<'p, 'tcx>, is_non_exhaustive: bool, ) -> PatStack<'p, 'tcx> { let mut result: SmallVec<_> = ctor_wild_subpatterns.iter().collect(); @@ -2326,7 +2359,7 @@ fn specialize_one_pattern<'p, 'tcx>( cx: &mut MatchCheckCtxt<'p, 'tcx>, pat: &'p Pat<'tcx>, constructor: &Constructor<'tcx>, - ctor_wild_subpatterns: &'p [Pat<'tcx>], + ctor_wild_subpatterns: &Fields<'p, 'tcx>, ) -> Option> { if let NonExhaustive = constructor { // Only a wildcard pattern can match the special extra constructor