about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_mir/hair/pattern/_match.rs92
1 files changed, 52 insertions, 40 deletions
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs
index 2bbe097047c..fb4dba2db5c 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir/hair/pattern/_match.rs
@@ -239,6 +239,7 @@ use rustc::ty::{self, Const, Ty, TyCtxt, TypeFoldable};
 use rustc::lint;
 use rustc::mir::interpret::{truncate, AllocId, ConstValue, Pointer, Scalar};
 use rustc::mir::Field;
+use rustc::util::captures::Captures;
 use rustc::util::common::ErrorReported;
 
 use syntax::attr::{SignedInt, UnsignedInt};
@@ -427,6 +428,11 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
         self.0.push(row)
     }
 
+    /// Iterate over the first component of each row
+    fn heads<'a>(&'a self) -> impl Iterator<Item = &'a Pat<'tcx>> + Captures<'p> {
+        self.0.iter().map(|r| r.head())
+    }
+
     /// This computes `D(self)`. See top of the file for explanations.
     fn specialize_wildcard(&self) -> Self {
         self.0.iter().filter_map(|r| r.specialize_wildcard()).collect()
@@ -635,6 +641,39 @@ impl<'tcx> Constructor<'tcx> {
             _ => bug!("bad constructor being displayed: `{:?}", self),
         }
     }
+
+    fn wildcard_subpatterns<'a>(
+        &self,
+        cx: &MatchCheckCtxt<'a, 'tcx>,
+        ty: Ty<'tcx>,
+    ) -> Vec<Pat<'tcx>> {
+        constructor_sub_pattern_tys(cx, self, ty)
+            .into_iter()
+            .map(|ty| Pat { ty, span: DUMMY_SP, kind: box PatKind::Wild })
+            .collect()
+    }
+
+    /// This computes the arity of a constructor. The arity of a constructor
+    /// is how many subpattern patterns of that constructor should be expanded to.
+    ///
+    /// For instance, a tuple pattern `(_, 42, Some([]))` has the arity of 3.
+    /// A struct pattern's arity is the number of fields it contains, etc.
+    fn arity<'a>(&self, cx: &MatchCheckCtxt<'a, 'tcx>, ty: Ty<'tcx>) -> u64 {
+        debug!("Constructor::arity({:#?}, {:?})", self, ty);
+        match ty.kind {
+            ty::Tuple(ref fs) => fs.len() as u64,
+            ty::Slice(..) | ty::Array(..) => match *self {
+                Slice(length) => length,
+                ConstantValue(..) => 0,
+                _ => bug!("bad slice pattern {:?} {:?}", self, ty),
+            },
+            ty::Ref(..) => 1,
+            ty::Adt(adt, _) => {
+                adt.variants[self.variant_index_for_adt(cx, adt)].fields.len() as u64
+            }
+            _ => 0,
+        }
+    }
 }
 
 #[derive(Clone, Debug)]
@@ -713,12 +752,7 @@ impl<'tcx> Witness<'tcx> {
         ctor: &Constructor<'tcx>,
         ty: Ty<'tcx>,
     ) -> Self {
-        let sub_pattern_tys = constructor_sub_pattern_tys(cx, ctor, ty);
-        self.0.extend(sub_pattern_tys.into_iter().map(|ty| Pat {
-            ty,
-            span: DUMMY_SP,
-            kind: box PatKind::Wild,
-        }));
+        self.0.extend(ctor.wildcard_subpatterns(cx, ty));
         self.apply_constructor(cx, ctor, ty)
     }
 
@@ -741,7 +775,7 @@ impl<'tcx> Witness<'tcx> {
         ctor: &Constructor<'tcx>,
         ty: Ty<'tcx>,
     ) -> Self {
-        let arity = constructor_arity(cx, ctor, ty);
+        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();
@@ -1347,9 +1381,9 @@ pub fn is_useful<'p, 'a, 'tcx>(
 
     assert!(rows.iter().all(|r| r.len() == v.len()));
 
-    let (ty, span) = rows
-        .iter()
-        .map(|r| (r.head().ty, r.head().span))
+    let (ty, span) = matrix
+        .heads()
+        .map(|r| (r.ty, r.span))
         .find(|(ty, _)| !ty.references_error())
         .unwrap_or((v.head().ty, v.head().span));
     let pcx = PatCtxt {
@@ -1373,7 +1407,7 @@ pub fn is_useful<'p, 'a, 'tcx>(
         // introducing uninhabited patterns for inaccessible fields. We
         // need to figure out how to model that.
         ty,
-        max_slice_length: max_slice_length(cx, rows.iter().map(|r| r.head()).chain(Some(v.head()))),
+        max_slice_length: max_slice_length(cx, matrix.heads().chain(Some(v.head()))),
         span,
     };
 
@@ -1397,10 +1431,8 @@ pub fn is_useful<'p, 'a, 'tcx>(
     } else {
         debug!("is_useful - expanding wildcard");
 
-        let used_ctors: Vec<Constructor<'_>> = rows
-            .iter()
-            .flat_map(|row| pat_constructors(cx, row.head(), pcx).unwrap_or(vec![]))
-            .collect();
+        let used_ctors: Vec<Constructor<'_>> =
+            matrix.heads().flat_map(|p| pat_constructors(cx, p, pcx).unwrap_or(vec![])).collect();
         debug!("used_ctors = {:#?}", used_ctors);
         // `all_ctors` are all the constructors for the given type, which
         // should all be represented (or caught with the wild pattern `_`).
@@ -1572,9 +1604,8 @@ fn is_useful_specialized<'p, 'a, 'tcx>(
     hir_id: HirId,
 ) -> Usefulness<'tcx> {
     debug!("is_useful_specialized({:#?}, {:#?}, {:?})", v, ctor, lty);
-    let sub_pat_tys = constructor_sub_pattern_tys(cx, &ctor, lty);
-    let wild_patterns_owned: Vec<_> =
-        sub_pat_tys.iter().map(|ty| Pat { ty, span: DUMMY_SP, kind: box PatKind::Wild }).collect();
+
+    let wild_patterns_owned = ctor.wildcard_subpatterns(cx, lty);
     let wild_patterns: Vec<_> = wild_patterns_owned.iter().collect();
     let matrix = matrix.specialize_constructor(cx, &ctor, &wild_patterns);
     match v.specialize_constructor(cx, &ctor, &wild_patterns) {
@@ -1637,26 +1668,6 @@ fn pat_constructors<'tcx>(
     }
 }
 
-/// This computes the arity of a constructor. The arity of a constructor
-/// is how many subpattern patterns of that constructor should be expanded to.
-///
-/// For instance, a tuple pattern `(_, 42, Some([]))` has the arity of 3.
-/// A struct pattern's arity is the number of fields it contains, etc.
-fn constructor_arity(cx: &MatchCheckCtxt<'a, 'tcx>, ctor: &Constructor<'tcx>, ty: Ty<'tcx>) -> u64 {
-    debug!("constructor_arity({:#?}, {:?})", ctor, ty);
-    match ty.kind {
-        ty::Tuple(ref fs) => fs.len() as u64,
-        ty::Slice(..) | ty::Array(..) => match *ctor {
-            Slice(length) => length,
-            ConstantValue(..) => 0,
-            _ => bug!("bad slice pattern {:?} {:?}", ctor, ty),
-        },
-        ty::Ref(..) => 1,
-        ty::Adt(adt, _) => adt.variants[ctor.variant_index_for_adt(cx, adt)].fields.len() as u64,
-        _ => 0,
-    }
-}
-
 /// This computes the types of the sub patterns that a constructor should be
 /// expanded to.
 ///
@@ -1833,7 +1844,7 @@ fn split_grouped_constructors<'p, 'tcx>(
     tcx: TyCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     ctors: Vec<Constructor<'tcx>>,
-    &Matrix(ref m): &Matrix<'p, 'tcx>,
+    matrix: &Matrix<'p, 'tcx>,
     ty: Ty<'tcx>,
     span: Span,
     hir_id: Option<HirId>,
@@ -1875,7 +1886,8 @@ fn split_grouped_constructors<'p, 'tcx>(
                 let mut overlaps = vec![];
                 // `borders` is the set of borders between equivalence classes: each equivalence
                 // class lies between 2 borders.
-                let row_borders = m
+                let row_borders = matrix
+                    .0
                     .iter()
                     .flat_map(|row| {
                         IntRange::from_pat(tcx, param_env, row.head()).map(|r| (r, row.len()))