about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNicholas Nethercote <nnethercote@mozilla.com>2019-10-04 11:02:04 +1000
committerNicholas Nethercote <nnethercote@mozilla.com>2019-10-04 16:58:44 +1000
commit9a1a3b9013221b90a9b02ecd23614b6e2fcf6a2d (patch)
treeed4b8d6da183c52cbe6ba00d86de37e70e38c3a9
parentf2023ac599c38a59f86552089e6791c5a73412d3 (diff)
downloadrust-9a1a3b9013221b90a9b02ecd23614b6e2fcf6a2d.tar.gz
rust-9a1a3b9013221b90a9b02ecd23614b6e2fcf6a2d.zip
Combine two `match` arms in `specialize()`.
This reduces the number of call sites for
`constructor_intersects_pattern()` from two to one, which the next
commit will take advantage of.
-rw-r--r--src/librustc_mir/hair/pattern/_match.rs138
1 files changed, 68 insertions, 70 deletions
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs
index d3bc61a4dde..cf8ef8c7699 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir/hair/pattern/_match.rs
@@ -434,6 +434,13 @@ enum Constructor<'tcx> {
 }
 
 impl<'tcx> Constructor<'tcx> {
+    fn is_slice(&self) -> bool {
+        match self {
+            Slice { .. } => true,
+            _ => false,
+        }
+    }
+
     fn variant_index_for_adt<'a>(
         &self,
         cx: &MatchCheckCtxt<'a, 'tcx>,
@@ -1766,85 +1773,76 @@ fn specialize<'p, 'a: 'p, 'tcx>(
             Some(smallvec![subpattern])
         }
 
-        PatKind::Constant { value } => {
-            match *constructor {
-                Slice(..) => {
-                    // we extract an `Option` for the pointer because slices of zero elements don't
-                    // necessarily point to memory, they are usually just integers. The only time
-                    // they should be pointing to memory is when they are subslices of nonzero
-                    // slices
-                    let (alloc, offset, n, ty) = match value.ty.kind {
-                        ty::Array(t, n) => {
-                            match value.val {
-                                ConstValue::ByRef { offset, alloc, .. } => (
-                                    alloc,
-                                    offset,
-                                    n.eval_usize(cx.tcx, cx.param_env),
-                                    t,
-                                ),
-                                _ => span_bug!(
-                                    pat.span,
-                                    "array pattern is {:?}", value,
-                                ),
-                            }
-                        },
-                        ty::Slice(t) => {
-                            match value.val {
-                                ConstValue::Slice { data, start, end } => (
-                                    data,
-                                    Size::from_bytes(start as u64),
-                                    (end - start) as u64,
-                                    t,
-                                ),
-                                ConstValue::ByRef { .. } => {
-                                    // FIXME(oli-obk): implement `deref` for `ConstValue`
-                                    return None;
-                                },
-                                _ => span_bug!(
-                                    pat.span,
-                                    "slice pattern constant must be scalar pair but is {:?}",
-                                    value,
-                                ),
-                            }
+        PatKind::Constant { value } if constructor.is_slice() => {
+            // We extract an `Option` for the pointer because slices of zero
+            // elements don't necessarily point to memory, they are usually
+            // just integers. The only time they should be pointing to memory
+            // is when they are subslices of nonzero slices.
+            let (alloc, offset, n, ty) = match value.ty.kind {
+                ty::Array(t, n) => {
+                    match value.val {
+                        ConstValue::ByRef { offset, alloc, .. } => (
+                            alloc,
+                            offset,
+                            n.eval_usize(cx.tcx, cx.param_env),
+                            t,
+                        ),
+                        _ => span_bug!(
+                            pat.span,
+                            "array pattern is {:?}", value,
+                        ),
+                    }
+                },
+                ty::Slice(t) => {
+                    match value.val {
+                        ConstValue::Slice { data, start, end } => (
+                            data,
+                            Size::from_bytes(start as u64),
+                            (end - start) as u64,
+                            t,
+                        ),
+                        ConstValue::ByRef { .. } => {
+                            // FIXME(oli-obk): implement `deref` for `ConstValue`
+                            return None;
                         },
                         _ => span_bug!(
                             pat.span,
-                            "unexpected const-val {:?} with ctor {:?}",
+                            "slice pattern constant must be scalar pair but is {:?}",
                             value,
-                            constructor,
                         ),
-                    };
-                    if wild_patterns.len() as u64 == n {
-                        // convert a constant slice/array pattern to a list of patterns.
-                        let layout = cx.tcx.layout_of(cx.param_env.and(ty)).ok()?;
-                        let ptr = Pointer::new(AllocId(0), offset);
-                        (0..n).map(|i| {
-                            let ptr = ptr.offset(layout.size * i, &cx.tcx).ok()?;
-                            let scalar = alloc.read_scalar(
-                                &cx.tcx, ptr, layout.size,
-                            ).ok()?;
-                            let scalar = scalar.not_undef().ok()?;
-                            let value = ty::Const::from_scalar(cx.tcx, scalar, ty);
-                            let pattern = Pat {
-                                ty,
-                                span: pat.span,
-                                kind: box PatKind::Constant { value },
-                            };
-                            Some(&*cx.pattern_arena.alloc(pattern))
-                        }).collect()
-                    } else {
-                        None
                     }
-                }
-                _ => {
-                    // If the constructor is a:
-                    //      Single value: add a row if the constructor equals the pattern.
-                    //      Range: add a row if the constructor contains the pattern.
-                    constructor_intersects_pattern(cx.tcx, cx.param_env, constructor, pat)
-                }
+                },
+                _ => span_bug!(
+                    pat.span,
+                    "unexpected const-val {:?} with ctor {:?}",
+                    value,
+                    constructor,
+                ),
+            };
+            if wild_patterns.len() as u64 == n {
+                // convert a constant slice/array pattern to a list of patterns.
+                let layout = cx.tcx.layout_of(cx.param_env.and(ty)).ok()?;
+                let ptr = Pointer::new(AllocId(0), offset);
+                (0..n).map(|i| {
+                    let ptr = ptr.offset(layout.size * i, &cx.tcx).ok()?;
+                    let scalar = alloc.read_scalar(
+                        &cx.tcx, ptr, layout.size,
+                    ).ok()?;
+                    let scalar = scalar.not_undef().ok()?;
+                    let value = ty::Const::from_scalar(cx.tcx, scalar, ty);
+                    let pattern = Pat {
+                        ty,
+                        span: pat.span,
+                        kind: box PatKind::Constant { value },
+                    };
+                    Some(&*cx.pattern_arena.alloc(pattern))
+                }).collect()
+            } else {
+                None
             }
         }
 
+        PatKind::Constant { .. } |
         PatKind::Range { .. } => {
             // If the constructor is a:
             //      Single value: add a row if the pattern contains the constructor.