about summary refs log tree commit diff
path: root/src/librustc_const_eval
diff options
context:
space:
mode:
authorOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>2018-01-16 09:24:38 +0100
committerOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>2018-03-08 08:08:14 +0100
commit918b6d763319863fb53c5b7bceebc14ad5fb4024 (patch)
tree02ca8d896e88377b900153d517665fa7c747b2ab /src/librustc_const_eval
parentc0574c054c1979a4d77822d4fe36ba7571760b00 (diff)
downloadrust-918b6d763319863fb53c5b7bceebc14ad5fb4024.tar.gz
rust-918b6d763319863fb53c5b7bceebc14ad5fb4024.zip
Produce instead of pointers
Diffstat (limited to 'src/librustc_const_eval')
-rw-r--r--src/librustc_const_eval/_match.rs180
-rw-r--r--src/librustc_const_eval/eval.rs180
-rw-r--r--src/librustc_const_eval/pattern.rs335
3 files changed, 456 insertions, 239 deletions
diff --git a/src/librustc_const_eval/_match.rs b/src/librustc_const_eval/_match.rs
index 8e3b99f2dbf..9e9eb4a81d0 100644
--- a/src/librustc_const_eval/_match.rs
+++ b/src/librustc_const_eval/_match.rs
@@ -28,6 +28,7 @@ use rustc::hir::RangeEnd;
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 
 use rustc::mir::Field;
+use rustc::mir::interpret::{Value, PrimVal};
 use rustc::util::common::ErrorReported;
 
 use syntax_pos::{Span, DUMMY_SP};
@@ -195,6 +196,41 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
                         }
                     })).collect()
                 }
+                box PatternKind::Constant {
+                    value: &ty::Const { val: ConstVal::Value(b), ty }
+                } => {
+                    match b {
+                        Value::ByVal(PrimVal::Ptr(ptr)) => {
+                            let is_array_ptr = ty
+                                .builtin_deref(true, ty::NoPreference)
+                                .and_then(|t| t.ty.builtin_index())
+                                .map_or(false, |t| t == tcx.types.u8);
+                            assert!(is_array_ptr);
+                            let alloc = tcx
+                                .interpret_interner
+                                .borrow()
+                                .get_alloc(ptr.alloc_id.0)
+                                .unwrap();
+                            assert_eq!(ptr.offset, 0);
+                            // FIXME: check length
+                            alloc.bytes.iter().map(|b| {
+                                &*pattern_arena.alloc(Pattern {
+                                    ty: tcx.types.u8,
+                                    span: pat.span,
+                                    kind: box PatternKind::Constant {
+                                        value: tcx.mk_const(ty::Const {
+                                            val: ConstVal::Value(Value::ByVal(
+                                                PrimVal::Bytes(*b as u128),
+                                            )),
+                                            ty: tcx.types.u8
+                                        })
+                                    }
+                                })
+                            }).collect()
+                        },
+                        _ => bug!("not a byte str: {:?}", b),
+                    }
+                }
                 _ => span_bug!(pat.span, "unexpected byte array pattern {:?}", pat)
             }
         }).clone()
@@ -422,13 +458,17 @@ fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
         ty::TyBool => {
             [true, false].iter().map(|&b| {
                 ConstantValue(cx.tcx.mk_const(ty::Const {
-                    val: ConstVal::Bool(b),
+                    val: if cx.tcx.sess.opts.debugging_opts.miri {
+                        ConstVal::Value(Value::ByVal(PrimVal::Bytes(b as u128)))
+                    } else {
+                        ConstVal::Bool(b)
+                    },
                     ty: cx.tcx.types.bool
                 }))
             }).collect()
         }
-        ty::TyArray(ref sub_ty, len) if len.val.to_const_int().is_some() => {
-            let len = len.val.to_const_int().unwrap().to_u64().unwrap();
+        ty::TyArray(ref sub_ty, len) if len.val.to_u128().is_some() => {
+            let len = len.val.unwrap_u64();
             if len != 0 && cx.is_uninhabited(sub_ty) {
                 vec![]
             } else {
@@ -461,7 +501,7 @@ fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
 }
 
 fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>(
-    _cx: &mut MatchCheckCtxt<'a, 'tcx>,
+    cx: &mut MatchCheckCtxt<'a, 'tcx>,
     patterns: I) -> u64
     where I: Iterator<Item=&'p Pattern<'tcx>>
 {
@@ -538,6 +578,25 @@ fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>(
             PatternKind::Constant { value: &ty::Const { val: ConstVal::ByteStr(b), .. } } => {
                 max_fixed_len = cmp::max(max_fixed_len, b.data.len() as u64);
             }
+            PatternKind::Constant {
+                value: &ty::Const {
+                    val: ConstVal::Value(Value::ByVal(PrimVal::Ptr(ptr))),
+                    ty,
+                }
+            } => {
+                let is_array_ptr = ty
+                    .builtin_deref(true, ty::NoPreference)
+                    .and_then(|t| t.ty.builtin_index())
+                    .map_or(false, |t| t == cx.tcx.types.u8);
+                if is_array_ptr {
+                    let alloc = cx.tcx
+                        .interpret_interner
+                        .borrow()
+                        .get_alloc(ptr.alloc_id.0)
+                        .unwrap();
+                    max_fixed_len = cmp::max(max_fixed_len, alloc.bytes.len() as u64);
+                }
+            }
             PatternKind::Slice { ref prefix, slice: None, ref suffix } => {
                 let fixed_len = prefix.len() as u64 + suffix.len() as u64;
                 max_fixed_len = cmp::max(max_fixed_len, fixed_len);
@@ -581,7 +640,7 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
                                        witness: WitnessPreference)
                                        -> Usefulness<'tcx> {
     let &Matrix(ref rows) = matrix;
-    debug!("is_useful({:?}, {:?})", matrix, v);
+    debug!("is_useful({:#?}, {:#?})", matrix, v);
 
     // The base case. We are pattern-matching on () and the return value is
     // based on whether our matrix has a row or not.
@@ -626,10 +685,10 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
         max_slice_length: max_slice_length(cx, rows.iter().map(|r| r[0]).chain(Some(v[0])))
     };
 
-    debug!("is_useful_expand_first_col: pcx={:?}, expanding {:?}", pcx, v[0]);
+    debug!("is_useful_expand_first_col: pcx={:#?}, expanding {:#?}", pcx, v[0]);
 
     if let Some(constructors) = pat_constructors(cx, v[0], pcx) {
-        debug!("is_useful - expanding constructors: {:?}", constructors);
+        debug!("is_useful - expanding constructors: {:#?}", constructors);
         constructors.into_iter().map(|c|
             is_useful_specialized(cx, matrix, v, c.clone(), pcx.ty, witness)
         ).find(|result| result.is_useful()).unwrap_or(NotUseful)
@@ -639,9 +698,9 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
         let used_ctors: Vec<Constructor> = rows.iter().flat_map(|row| {
             pat_constructors(cx, row[0], pcx).unwrap_or(vec![])
         }).collect();
-        debug!("used_ctors = {:?}", used_ctors);
+        debug!("used_ctors = {:#?}", used_ctors);
         let all_ctors = all_constructors(cx, pcx);
-        debug!("all_ctors = {:?}", all_ctors);
+        debug!("all_ctors = {:#?}", all_ctors);
         let missing_ctors: Vec<Constructor> = all_ctors.iter().filter(|c| {
             !used_ctors.contains(*c)
         }).cloned().collect();
@@ -669,7 +728,7 @@ pub fn is_useful<'p, 'a: 'p, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
             all_ctors.is_empty() && !cx.is_uninhabited(pcx.ty);
         let is_declared_nonexhaustive =
             cx.is_non_exhaustive_enum(pcx.ty) && !cx.is_local(pcx.ty);
-        debug!("missing_ctors={:?} is_privately_empty={:?} is_declared_nonexhaustive={:?}",
+        debug!("missing_ctors={:#?} is_privately_empty={:#?} is_declared_nonexhaustive={:#?}",
                missing_ctors, is_privately_empty, is_declared_nonexhaustive);
 
         // For privately empty and non-exhaustive enums, we work as if there were an "extra"
@@ -769,7 +828,7 @@ fn is_useful_specialized<'p, 'a:'p, 'tcx: 'a>(
     lty: Ty<'tcx>,
     witness: WitnessPreference) -> Usefulness<'tcx>
 {
-    debug!("is_useful_specialized({:?}, {:?}, {:?})", v, ctor, lty);
+    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| {
         Pattern {
@@ -821,7 +880,7 @@ fn pat_constructors<'tcx>(_cx: &mut MatchCheckCtxt,
             Some(vec![ConstantRange(lo, hi, end)]),
         PatternKind::Array { .. } => match pcx.ty.sty {
             ty::TyArray(_, length) => Some(vec![
-                Slice(length.val.to_const_int().unwrap().to_u64().unwrap())
+                Slice(length.val.unwrap_u64())
             ]),
             _ => span_bug!(pat.span, "bad ty {:?} for array pattern", pcx.ty)
         },
@@ -842,7 +901,7 @@ fn pat_constructors<'tcx>(_cx: &mut MatchCheckCtxt,
 /// 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, ctor: &Constructor, ty: Ty) -> u64 {
-    debug!("constructor_arity({:?}, {:?})", ctor, ty);
+    debug!("constructor_arity({:#?}, {:?})", ctor, ty);
     match ty.sty {
         ty::TyTuple(ref fs, _) => fs.len() as u64,
         ty::TySlice(..) | ty::TyArray(..) => match *ctor {
@@ -866,12 +925,13 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>,
                                              ctor: &Constructor,
                                              ty: Ty<'tcx>) -> Vec<Ty<'tcx>>
 {
-    debug!("constructor_sub_pattern_tys({:?}, {:?})", ctor, ty);
+    debug!("constructor_sub_pattern_tys({:#?}, {:?})", ctor, ty);
     match ty.sty {
         ty::TyTuple(ref fs, _) => fs.into_iter().map(|t| *t).collect(),
         ty::TySlice(ty) | ty::TyArray(ty, _) => match *ctor {
             Slice(length) => (0..length).map(|_| ty).collect(),
             ConstantValue(_) => vec![],
+            Single => vec![ty],
             _ => bug!("bad slice pattern {:?} {:?}", ctor, ty)
         },
         ty::TyRef(_, ref ty_and_mut) => vec![ty_and_mut.ty],
@@ -880,6 +940,9 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>,
                 // Use T as the sub pattern type of Box<T>.
                 vec![substs.type_at(0)]
             } else {
+                if let ConstantValue(_) = *ctor {
+                    return vec![];
+                }
                 adt.variants[ctor.variant_index_for_adt(adt)].fields.iter().map(|field| {
                     let is_visible = adt.is_enum()
                         || field.vis.is_accessible_from(cx.module, cx.tcx);
@@ -901,14 +964,30 @@ fn constructor_sub_pattern_tys<'a, 'tcx: 'a>(cx: &MatchCheckCtxt<'a, 'tcx>,
     }
 }
 
-fn slice_pat_covered_by_constructor(_tcx: TyCtxt, _span: Span,
+fn slice_pat_covered_by_constructor(tcx: TyCtxt, _span: Span,
                                     ctor: &Constructor,
                                     prefix: &[Pattern],
                                     slice: &Option<Pattern>,
                                     suffix: &[Pattern])
                                     -> Result<bool, ErrorReported> {
-    let data = match *ctor {
+    let data: &[u8] = match *ctor {
         ConstantValue(&ty::Const { val: ConstVal::ByteStr(b), .. }) => b.data,
+        ConstantValue(&ty::Const { val: ConstVal::Value(
+            Value::ByVal(PrimVal::Ptr(ptr))
+        ), ty }) => {
+            let is_array_ptr = ty
+                .builtin_deref(true, ty::NoPreference)
+                .and_then(|t| t.ty.builtin_index())
+                .map_or(false, |t| t == tcx.types.u8);
+            assert!(is_array_ptr);
+            tcx
+                .interpret_interner
+                .borrow()
+                .get_alloc(ptr.alloc_id.0)
+                .unwrap()
+                .bytes
+                .as_ref()
+        }
         _ => bug!()
     };
 
@@ -928,6 +1007,12 @@ fn slice_pat_covered_by_constructor(_tcx: TyCtxt, _span: Span,
                         return Ok(false);
                     }
                 },
+                ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))) => {
+                    assert_eq!(b as u8 as u128, b);
+                    if b as u8 != *ch {
+                        return Ok(false);
+                    }
+                }
                 _ => span_bug!(pat.span, "bad const u8 {:?}", value)
             },
             _ => {}
@@ -937,32 +1022,43 @@ fn slice_pat_covered_by_constructor(_tcx: TyCtxt, _span: Span,
     Ok(true)
 }
 
-fn constructor_covered_by_range(tcx: TyCtxt, span: Span,
-                                ctor: &Constructor,
+fn constructor_covered_by_range(ctor: &Constructor,
                                 from: &ConstVal, to: &ConstVal,
-                                end: RangeEnd)
+                                end: RangeEnd,
+                                ty: Ty)
                                 -> Result<bool, ErrorReported> {
-    let cmp_from = |c_from| Ok(compare_const_vals(tcx, span, c_from, from)? != Ordering::Less);
-    let cmp_to = |c_to| compare_const_vals(tcx, span, c_to, to);
+    trace!("constructor_covered_by_range {:#?}, {:#?}, {:#?}, {}", ctor, from, to, ty);
+    let cmp_from = |c_from| compare_const_vals(c_from, from, ty)
+        .map(|res| res != Ordering::Less);
+    let cmp_to = |c_to| compare_const_vals(c_to, to, ty);
+    macro_rules! some_or_ok {
+        ($e:expr) => {
+            match $e {
+                Some(to) => to,
+                None => return Ok(false), // not char or int
+            }
+        };
+    }
     match *ctor {
         ConstantValue(value) => {
-            let to = cmp_to(&value.val)?;
+            let to = some_or_ok!(cmp_to(&value.val));
             let end = (to == Ordering::Less) ||
                       (end == RangeEnd::Included && to == Ordering::Equal);
-            Ok(cmp_from(&value.val)? && end)
+            Ok(some_or_ok!(cmp_from(&value.val)) && end)
         },
         ConstantRange(from, to, RangeEnd::Included) => {
-            let to = cmp_to(&to.val)?;
+            let to = some_or_ok!(cmp_to(&to.val));
             let end = (to == Ordering::Less) ||
                       (end == RangeEnd::Included && to == Ordering::Equal);
-            Ok(cmp_from(&from.val)? && end)
+            Ok(some_or_ok!(cmp_from(&from.val)) && end)
         },
         ConstantRange(from, to, RangeEnd::Excluded) => {
-            let to = cmp_to(&to.val)?;
+            let to = some_or_ok!(cmp_to(&to.val));
             let end = (to == Ordering::Less) ||
                       (end == RangeEnd::Excluded && to == Ordering::Equal);
-            Ok(cmp_from(&from.val)? && end)
+            Ok(some_or_ok!(cmp_from(&from.val)) && end)
         }
+        Variant(_) |
         Single => Ok(true),
         _ => bug!(),
     }
@@ -979,7 +1075,7 @@ fn patterns_for_variant<'p, 'a: 'p, 'tcx: 'a>(
         result[subpat.field.index()] = &subpat.pattern;
     }
 
-    debug!("patterns_for_variant({:?}, {:?}) = {:?}", subpatterns, wild_patterns, result);
+    debug!("patterns_for_variant({:#?}, {:#?}) = {:#?}", subpatterns, wild_patterns, result);
     result
 }
 
@@ -994,7 +1090,7 @@ fn patterns_for_variant<'p, 'a: 'p, 'tcx: 'a>(
 fn specialize<'p, 'a: 'p, 'tcx: 'a>(
     cx: &mut MatchCheckCtxt<'a, 'tcx>,
     r: &[&'p Pattern<'tcx>],
-    constructor: &Constructor,
+    constructor: &Constructor<'tcx>,
     wild_patterns: &[&'p Pattern<'tcx>])
     -> Option<Vec<&'p Pattern<'tcx>>>
 {
@@ -1031,12 +1127,32 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
                             None
                         }
                     }
+                    ConstVal::Value(Value::ByVal(PrimVal::Ptr(ptr))) => {
+                        let is_array_ptr = value.ty
+                            .builtin_deref(true, ty::NoPreference)
+                            .and_then(|t| t.ty.builtin_index())
+                            .map_or(false, |t| t == cx.tcx.types.u8);
+                        assert!(is_array_ptr);
+                        let data_len = cx.tcx
+                            .interpret_interner
+                            .borrow()
+                            .get_alloc(ptr.alloc_id.0)
+                            .unwrap()
+                            .bytes
+                            .len();
+                        if wild_patterns.len() == data_len {
+                            Some(cx.lower_byte_str_pattern(pat))
+                        } else {
+                            None
+                        }
+                    }
                     _ => span_bug!(pat.span,
                         "unexpected const-val {:?} with ctor {:?}", value, constructor)
                 },
                 _ => {
                     match constructor_covered_by_range(
-                        cx.tcx, pat.span, constructor, &value.val, &value.val, RangeEnd::Included
+                        constructor, &value.val, &value.val, RangeEnd::Included,
+                        value.ty,
                             ) {
                         Ok(true) => Some(vec![]),
                         Ok(false) => None,
@@ -1048,7 +1164,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
 
         PatternKind::Range { lo, hi, ref end } => {
             match constructor_covered_by_range(
-                cx.tcx, pat.span, constructor, &lo.val, &hi.val, end.clone()
+                constructor, &lo.val, &hi.val, end.clone(), lo.ty,
             ) {
                 Ok(true) => Some(vec![]),
                 Ok(false) => None,
@@ -1092,7 +1208,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
             }
         }
     };
-    debug!("specialize({:?}, {:?}) = {:?}", r[0], wild_patterns, head);
+    debug!("specialize({:#?}, {:#?}) = {:#?}", r[0], wild_patterns, head);
 
     head.map(|mut head| {
         head.extend_from_slice(&r[1 ..]);
diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs
index 2a571fa8264..58fe40d12be 100644
--- a/src/librustc_const_eval/eval.rs
+++ b/src/librustc_const_eval/eval.rs
@@ -26,7 +26,6 @@ use syntax::abi::Abi;
 use syntax::ast;
 use syntax::attr;
 use rustc::hir::{self, Expr};
-use syntax_pos::Span;
 
 use std::cmp::Ordering;
 
@@ -104,60 +103,10 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
       hir::ExprUnary(hir::UnNeg, ref inner) => {
         // unary neg literals already got their sign during creation
         if let hir::ExprLit(ref lit) = inner.node {
-            use syntax::ast::*;
-            use syntax::ast::LitIntType::*;
-            const I8_OVERFLOW: u128 = i8::min_value() as u8 as u128;
-            const I16_OVERFLOW: u128 = i16::min_value() as u16 as u128;
-            const I32_OVERFLOW: u128 = i32::min_value() as u32 as u128;
-            const I64_OVERFLOW: u128 = i64::min_value() as u64 as u128;
-            const I128_OVERFLOW: u128 = i128::min_value() as u128;
-            let negated = match (&lit.node, &ty.sty) {
-                (&LitKind::Int(I8_OVERFLOW, _), &ty::TyInt(IntTy::I8)) |
-                (&LitKind::Int(I8_OVERFLOW, Signed(IntTy::I8)), _) => {
-                    Some(I8(i8::min_value()))
-                },
-                (&LitKind::Int(I16_OVERFLOW, _), &ty::TyInt(IntTy::I16)) |
-                (&LitKind::Int(I16_OVERFLOW, Signed(IntTy::I16)), _) => {
-                    Some(I16(i16::min_value()))
-                },
-                (&LitKind::Int(I32_OVERFLOW, _), &ty::TyInt(IntTy::I32)) |
-                (&LitKind::Int(I32_OVERFLOW, Signed(IntTy::I32)), _) => {
-                    Some(I32(i32::min_value()))
-                },
-                (&LitKind::Int(I64_OVERFLOW, _), &ty::TyInt(IntTy::I64)) |
-                (&LitKind::Int(I64_OVERFLOW, Signed(IntTy::I64)), _) => {
-                    Some(I64(i64::min_value()))
-                },
-                (&LitKind::Int(I128_OVERFLOW, _), &ty::TyInt(IntTy::I128)) |
-                (&LitKind::Int(I128_OVERFLOW, Signed(IntTy::I128)), _) => {
-                    Some(I128(i128::min_value()))
-                },
-                (&LitKind::Int(n, _), &ty::TyInt(IntTy::Isize)) |
-                (&LitKind::Int(n, Signed(IntTy::Isize)), _) => {
-                    match tcx.sess.target.isize_ty {
-                        IntTy::I16 => if n == I16_OVERFLOW {
-                            Some(Isize(Is16(i16::min_value())))
-                        } else {
-                            None
-                        },
-                        IntTy::I32 => if n == I32_OVERFLOW {
-                            Some(Isize(Is32(i32::min_value())))
-                        } else {
-                            None
-                        },
-                        IntTy::I64 => if n == I64_OVERFLOW {
-                            Some(Isize(Is64(i64::min_value())))
-                        } else {
-                            None
-                        },
-                        _ => span_bug!(e.span, "typeck error")
-                    }
-                },
-                _ => None
+            return match lit_to_const(&lit.node, tcx, ty, true) {
+                Ok(val) => Ok(mk_const(val)),
+                Err(err) => signal!(e, err),
             };
-            if let Some(i) = negated {
-                return Ok(mk_const(Integral(i)));
-            }
         }
         mk_const(match cx.eval(inner)?.val {
           Float(f) => Float(-f),
@@ -377,7 +326,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
           };
           callee_cx.eval(&body.value)?
       },
-      hir::ExprLit(ref lit) => match lit_to_const(&lit.node, tcx, ty) {
+      hir::ExprLit(ref lit) => match lit_to_const(&lit.node, tcx, ty, false) {
           Ok(val) => mk_const(val),
           Err(err) => signal!(e, err),
       },
@@ -438,7 +387,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
       }
       hir::ExprRepeat(ref elem, _) => {
           let n = match ty.sty {
-            ty::TyArray(_, n) => n.val.to_const_int().unwrap().to_u64().unwrap(),
+            ty::TyArray(_, n) => n.val.unwrap_u64(),
             _ => span_bug!(e.span, "typeck error")
           };
           mk_const(Aggregate(Repeat(cx.eval(elem)?, n)))
@@ -447,7 +396,8 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
         if let Aggregate(Tuple(fields)) = cx.eval(base)?.val {
             fields[index.node]
         } else {
-            signal!(base, ExpectedConstTuple);
+            span_bug!(base.span, "{:#?}", cx.eval(base)?.val);
+            //signal!(base, ExpectedConstTuple);
         }
       }
       hir::ExprField(ref base, field_name) => {
@@ -557,7 +507,7 @@ fn cast_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             },
             ty::TyRef(_, ty::TypeAndMut { ref ty, mutbl: hir::MutImmutable }) => match ty.sty {
                 ty::TyArray(ty, n) => {
-                    let n = n.val.to_const_int().unwrap().to_u64().unwrap();
+                    let n = n.val.unwrap_u64();
                     if ty == tcx.types.u8 && n == b.data.len() as u64 {
                         Ok(val)
                     } else {
@@ -583,13 +533,66 @@ fn cast_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 }
 
-fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind,
+pub fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind,
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                          mut ty: Ty<'tcx>)
+                          mut ty: Ty<'tcx>,
+                          neg: bool)
                           -> Result<ConstVal<'tcx>, ErrKind<'tcx>> {
     use syntax::ast::*;
     use syntax::ast::LitIntType::*;
 
+    if tcx.sess.opts.debugging_opts.miri {
+        use rustc::mir::interpret::*;
+        let lit = match *lit {
+            LitKind::Str(ref s, _) => {
+                let s = s.as_str();
+                let id = tcx.allocate_cached(s.as_bytes());
+                let ptr = MemoryPointer::new(AllocId(id), 0);
+                Value::ByValPair(
+                    PrimVal::Ptr(ptr),
+                    PrimVal::from_u128(s.len() as u128),
+                )
+            },
+            LitKind::ByteStr(ref data) => {
+                let id = tcx.allocate_cached(data);
+                let ptr = MemoryPointer::new(AllocId(id), 0);
+                Value::ByVal(PrimVal::Ptr(ptr))
+            },
+            LitKind::Byte(n) => Value::ByVal(PrimVal::Bytes(n as u128)),
+            LitKind::Int(n, _) if neg => {
+                let n = n as i128;
+                let n = n.overflowing_neg().0;
+                Value::ByVal(PrimVal::Bytes(n as u128))
+            },
+            LitKind::Int(n, _) => Value::ByVal(PrimVal::Bytes(n as u128)),
+            LitKind::Float(n, fty) => {
+                let n = n.as_str();
+                let mut f = parse_float(&n, fty)?;
+                if neg {
+                    f = -f;
+                }
+                let bits = f.bits;
+                Value::ByVal(PrimVal::Bytes(bits))
+            }
+            LitKind::FloatUnsuffixed(n) => {
+                let fty = match ty.sty {
+                    ty::TyFloat(fty) => fty,
+                    _ => bug!()
+                };
+                let n = n.as_str();
+                let mut f = parse_float(&n, fty)?;
+                if neg {
+                    f = -f;
+                }
+                let bits = f.bits;
+                Value::ByVal(PrimVal::Bytes(bits))
+            }
+            LitKind::Bool(b) => Value::ByVal(PrimVal::Bytes(b as u128)),
+            LitKind::Char(c) => Value::ByVal(PrimVal::Bytes(c as u128)),
+        };
+        return Ok(ConstVal::Value(lit));
+    }
+
     if let ty::TyAdt(adt, _) = ty.sty {
         if adt.is_enum() {
             ty = adt.repr.discr_type().to_ty(tcx)
@@ -604,26 +607,38 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind,
             match (&ty.sty, hint) {
                 (&ty::TyInt(ity), _) |
                 (_, Signed(ity)) => {
-                    Ok(Integral(ConstInt::new_signed_truncating(n as i128,
+                    let mut n = n as i128;
+                    if neg {
+                        n = n.overflowing_neg().0;
+                    }
+                    Ok(Integral(ConstInt::new_signed_truncating(n,
                         ity, tcx.sess.target.isize_ty)))
                 }
                 (&ty::TyUint(uty), _) |
                 (_, Unsigned(uty)) => {
-                    Ok(Integral(ConstInt::new_unsigned_truncating(n as u128,
+                    Ok(Integral(ConstInt::new_unsigned_truncating(n,
                         uty, tcx.sess.target.usize_ty)))
                 }
                 _ => bug!()
             }
         }
         LitKind::Float(n, fty) => {
-            parse_float(&n.as_str(), fty).map(Float)
+            let mut f = parse_float(&n.as_str(), fty)?;
+            if neg {
+                f = -f;
+            }
+            Ok(Float(f))
         }
         LitKind::FloatUnsuffixed(n) => {
             let fty = match ty.sty {
                 ty::TyFloat(fty) => fty,
                 _ => bug!()
             };
-            parse_float(&n.as_str(), fty).map(Float)
+            let mut f = parse_float(&n.as_str(), fty)?;
+            if neg {
+                f = -f;
+            }
+            Ok(Float(f))
         }
         LitKind::Bool(b) => Ok(Bool(b)),
         LitKind::Char(c) => Ok(Char(c)),
@@ -638,36 +653,31 @@ fn parse_float<'tcx>(num: &str, fty: ast::FloatTy)
     })
 }
 
-pub fn compare_const_vals(tcx: TyCtxt, span: Span, a: &ConstVal, b: &ConstVal)
-                          -> Result<Ordering, ErrorReported>
-{
-    let result = match (a, b) {
+pub fn compare_const_vals(a: &ConstVal, b: &ConstVal, ty: Ty) -> Option<Ordering> {
+    trace!("compare_const_vals: {:?}, {:?}", a, b);
+    use rustc::mir::interpret::{Value, PrimVal};
+    match (a, b) {
         (&Integral(a), &Integral(b)) => a.try_cmp(b).ok(),
-        (&Float(a), &Float(b)) => a.try_cmp(b).ok(),
-        (&Str(ref a), &Str(ref b)) => Some(a.cmp(b)),
-        (&Bool(a), &Bool(b)) => Some(a.cmp(&b)),
-        (&ByteStr(a), &ByteStr(b)) => Some(a.data.cmp(b.data)),
         (&Char(a), &Char(b)) => Some(a.cmp(&b)),
+        (&Value(Value::ByVal(PrimVal::Bytes(a))),
+         &Value(Value::ByVal(PrimVal::Bytes(b)))) => {
+            Some(if ty.is_signed() {
+                (a as i128).cmp(&(b as i128))
+            } else {
+                a.cmp(&b)
+            })
+        },
+        _ if a == b => Some(Ordering::Equal),
         _ => None,
-    };
-
-    match result {
-        Some(result) => Ok(result),
-        None => {
-            // FIXME: can this ever be reached?
-            tcx.sess.delay_span_bug(span,
-                &format!("type mismatch comparing {:?} and {:?}", a, b));
-            Err(ErrorReported)
-        }
     }
 }
 
 impl<'a, 'tcx> ConstContext<'a, 'tcx> {
     pub fn compare_lit_exprs(&self,
-                             span: Span,
                              a: &'tcx Expr,
-                             b: &'tcx Expr) -> Result<Ordering, ErrorReported> {
+                             b: &'tcx Expr) -> Result<Option<Ordering>, ErrorReported> {
         let tcx = self.tcx;
+        let ty = self.tables.expr_ty(a);
         let a = match self.eval(a) {
             Ok(a) => a,
             Err(e) => {
@@ -682,6 +692,6 @@ impl<'a, 'tcx> ConstContext<'a, 'tcx> {
                 return Err(ErrorReported);
             }
         };
-        compare_const_vals(tcx, span, &a.val, &b.val)
+        Ok(compare_const_vals(&a.val, &b.val, ty))
     }
 }
diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs
index a09e2f2edd5..a2daf22c3b4 100644
--- a/src/librustc_const_eval/pattern.rs
+++ b/src/librustc_const_eval/pattern.rs
@@ -10,8 +10,9 @@
 
 use eval;
 
-use rustc::middle::const_val::{ConstEvalErr, ConstVal};
+use rustc::middle::const_val::{ConstEvalErr, ConstVal, ConstAggregate};
 use rustc::mir::{Field, BorrowKind, Mutability};
+use rustc::mir::interpret::{Value, PrimVal};
 use rustc::ty::{self, TyCtxt, AdtDef, Ty, Region};
 use rustc::ty::subst::{Substs, Kind};
 use rustc::hir::{self, PatKind, RangeEnd};
@@ -110,22 +111,35 @@ pub enum PatternKind<'tcx> {
     },
 }
 
-fn print_const_val(value: &ConstVal, f: &mut fmt::Formatter) -> fmt::Result {
-    match *value {
+fn print_const_val(value: &ty::Const, f: &mut fmt::Formatter) -> fmt::Result {
+    match value.val {
         ConstVal::Float(ref x) => write!(f, "{}", x),
         ConstVal::Integral(ref i) => write!(f, "{}", i),
         ConstVal::Str(ref s) => write!(f, "{:?}", &s[..]),
         ConstVal::ByteStr(b) => write!(f, "{:?}", b.data),
         ConstVal::Bool(b) => write!(f, "{:?}", b),
         ConstVal::Char(c) => write!(f, "{:?}", c),
+        ConstVal::Value(v) => print_miri_value(v, value.ty, f),
         ConstVal::Variant(_) |
         ConstVal::Function(..) |
         ConstVal::Aggregate(_) |
-        ConstVal::Value(_) |
         ConstVal::Unevaluated(..) => bug!("{:?} not printable in a pattern", value)
     }
 }
 
+fn print_miri_value(value: Value, ty: Ty, f: &mut fmt::Formatter) -> fmt::Result {
+    use rustc::ty::TypeVariants::*;
+    match (value, &ty.sty) {
+        (Value::ByVal(PrimVal::Bytes(0)), &TyBool) => write!(f, "false"),
+        (Value::ByVal(PrimVal::Bytes(1)), &TyBool) => write!(f, "true"),
+        (Value::ByVal(PrimVal::Bytes(n)), &TyUint(..)) => write!(f, "{:?}", n),
+        (Value::ByVal(PrimVal::Bytes(n)), &TyInt(..)) => write!(f, "{:?}", n as i128),
+        (Value::ByVal(PrimVal::Bytes(n)), &TyChar) =>
+            write!(f, "{:?}", ::std::char::from_u32(n as u32).unwrap()),
+        _ => bug!("{:?}: {} not printable in a pattern", value, ty),
+    }
+}
+
 impl<'tcx> fmt::Display for Pattern<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self.kind {
@@ -233,15 +247,15 @@ impl<'tcx> fmt::Display for Pattern<'tcx> {
                 write!(f, "{}", subpattern)
             }
             PatternKind::Constant { value } => {
-                print_const_val(&value.val, f)
+                print_const_val(value, f)
             }
             PatternKind::Range { lo, hi, end } => {
-                print_const_val(&lo.val, f)?;
+                print_const_val(lo, f)?;
                 match end {
                     RangeEnd::Included => write!(f, "...")?,
                     RangeEnd::Excluded => write!(f, "..")?,
                 }
-                print_const_val(&hi.val, f)
+                print_const_val(hi, f)
             }
             PatternKind::Slice { ref prefix, ref slice, ref suffix } |
             PatternKind::Array { ref prefix, ref slice, ref suffix } => {
@@ -362,7 +376,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
             }
 
             PatKind::Path(ref qpath) => {
-                return self.lower_path(qpath, pat.hir_id, pat.id, pat.span);
+                return self.lower_path(qpath, pat.hir_id, pat.span);
             }
 
             PatKind::Ref(ref subpattern, _) |
@@ -581,7 +595,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
 
             ty::TyArray(_, len) => {
                 // fixed-length array
-                let len = len.val.to_const_int().unwrap().to_u64().unwrap();
+                let len = len.val.unwrap_u64();
                 assert!(len >= prefix.len() as u64 + suffix.len() as u64);
                 PatternKind::Array { prefix: prefix, slice: slice, suffix: suffix }
             }
@@ -632,7 +646,6 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
     fn lower_path(&mut self,
                   qpath: &hir::QPath,
                   id: hir::HirId,
-                  pat_id: ast::NodeId,
                   span: Span)
                   -> Pattern<'tcx> {
         let ty = self.tables.node_id_to_type(id);
@@ -644,29 +657,23 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
         let kind = match def {
             Def::Const(def_id) | Def::AssociatedConst(def_id) => {
                 let substs = self.tables.node_substs(id);
-                match eval::lookup_const_by_id(self.tcx, self.param_env.and((def_id, substs))) {
-                    Some((def_id, substs)) => {
-                        // Enter the inlined constant's tables&substs temporarily.
-                        let old_tables = self.tables;
-                        let old_substs = self.substs;
-                        self.tables = self.tcx.typeck_tables_of(def_id);
-                        self.substs = substs;
-                        let body = if let Some(id) = self.tcx.hir.as_local_node_id(def_id) {
-                            self.tcx.hir.body(self.tcx.hir.body_owned_by(id))
-                        } else {
-                            self.tcx.extern_const_body(def_id).body
-                        };
-                        let pat = self.lower_const_expr(&body.value, pat_id, span);
-                        self.tables = old_tables;
-                        self.substs = old_substs;
-                        return pat;
-                    }
-                    None => {
-                        self.errors.push(if is_associated_const {
-                            PatternError::AssociatedConstInPattern(span)
-                        } else {
-                            PatternError::StaticInPattern(span)
-                        });
+                match self.tcx.at(span).const_eval(self.param_env.and((def_id, substs))) {
+                    Ok(value) => {
+                        if self.tcx.sess.opts.debugging_opts.miri {
+                            if let ConstVal::Value(_) = value.val {} else {
+                                panic!("const eval produced non-miri value: {:#?}", value);
+                            }
+                        }
+                        let instance = ty::Instance::resolve(
+                            self.tcx,
+                            self.param_env,
+                            def_id,
+                            substs,
+                        ).unwrap();
+                        return self.const_to_pat(instance, value, span)
+                    },
+                    Err(e) => {
+                        self.errors.push(PatternError::ConstEval(e));
                         PatternKind::Wild
                     }
                 }
@@ -682,6 +689,52 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
     }
 
     fn lower_lit(&mut self, expr: &'tcx hir::Expr) -> PatternKind<'tcx> {
+        if self.tcx.sess.opts.debugging_opts.miri {
+            return match expr.node {
+                hir::ExprLit(ref lit) => {
+                    let ty = self.tables.expr_ty(expr);
+                    match ::eval::lit_to_const(&lit.node, self.tcx, ty, false) {
+                        Ok(value) => PatternKind::Constant {
+                            value: self.tcx.mk_const(ty::Const {
+                                ty,
+                                val: value,
+                            }),
+                        },
+                        Err(e) => {
+                            self.errors.push(PatternError::ConstEval(ConstEvalErr {
+                                span: lit.span,
+                                kind: e,
+                            }));
+                            PatternKind::Wild
+                        },
+                    }
+                },
+                hir::ExprPath(ref qpath) => *self.lower_path(qpath, expr.hir_id, expr.span).kind,
+                hir::ExprUnary(hir::UnNeg, ref expr) => {
+                    let ty = self.tables.expr_ty(expr);
+                    let lit = match expr.node {
+                        hir::ExprLit(ref lit) => lit,
+                        _ => span_bug!(expr.span, "not a literal: {:?}", expr),
+                    };
+                    match ::eval::lit_to_const(&lit.node, self.tcx, ty, true) {
+                        Ok(value) => PatternKind::Constant {
+                            value: self.tcx.mk_const(ty::Const {
+                                ty,
+                                val: value,
+                            }),
+                        },
+                        Err(e) => {
+                            self.errors.push(PatternError::ConstEval(ConstEvalErr {
+                                span: lit.span,
+                                kind: e,
+                            }));
+                            PatternKind::Wild
+                        },
+                    }
+                }
+                _ => span_bug!(expr.span, "not a literal: {:?}", expr),
+            }
+        }
         let const_cx = eval::ConstContext::new(self.tcx,
                                                self.param_env.and(self.substs),
                                                self.tables);
@@ -701,118 +754,156 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
         }
     }
 
-    fn lower_const_expr(&mut self,
-                        expr: &'tcx hir::Expr,
-                        pat_id: ast::NodeId,
-                        span: Span)
-                        -> Pattern<'tcx> {
-        let pat_ty = self.tables.expr_ty(expr);
-        debug!("expr={:?} pat_ty={:?} pat_id={}", expr, pat_ty, pat_id);
-        match pat_ty.sty {
+    fn const_to_pat(
+        &self,
+        instance: ty::Instance<'tcx>,
+        cv: &'tcx ty::Const<'tcx>,
+        span: Span,
+    ) -> Pattern<'tcx> {
+        debug!("const_to_pat: cv={:#?}", cv);
+        let kind = match cv.ty.sty {
             ty::TyFloat(_) => {
                 self.tcx.sess.span_err(span, "floating point constants cannot be used in patterns");
+                PatternKind::Wild
             }
             ty::TyAdt(adt_def, _) if adt_def.is_union() => {
                 // Matching on union fields is unsafe, we can't hide it in constants
                 self.tcx.sess.span_err(span, "cannot use unions in constant patterns");
+                PatternKind::Wild
             }
+            ty::TyAdt(adt_def, _) if !self.tcx.has_attr(adt_def.did, "structural_match") => {
+                let msg = format!("to use a constant of type `{}` in a pattern, \
+                                    `{}` must be annotated with `#[derive(PartialEq, Eq)]`",
+                                    self.tcx.item_path_str(adt_def.did),
+                                    self.tcx.item_path_str(adt_def.did));
+                self.tcx.sess.span_err(span, &msg);
+                PatternKind::Wild
+            },
+            ty::TyAdt(adt_def, substs) if adt_def.is_enum() => {
+                match cv.val {
+                    ConstVal::Value(val) => {
+                        let discr = self.tcx.const_discr(self.param_env.and((
+                            instance, val, cv.ty
+                        ))).unwrap();
+                        let variant_index = adt_def
+                            .discriminants(self.tcx)
+                            .position(|var| var.to_u128_unchecked() == discr)
+                            .unwrap();
+                        PatternKind::Variant {
+                            adt_def,
+                            substs,
+                            variant_index,
+                            subpatterns: adt_def
+                                .variants[variant_index]
+                                .fields
+                                .iter()
+                                .enumerate()
+                                .map(|(i, _)| {
+                                let field = Field::new(i);
+                                let val = match cv.val {
+                                    ConstVal::Value(miri) => self.tcx.const_val_field(
+                                        self.param_env.and((instance, field, miri, cv.ty)),
+                                    ).unwrap(),
+                                    _ => bug!("{:#?} is not a valid tuple", cv),
+                                };
+                                FieldPattern {
+                                    field,
+                                    pattern: self.const_to_pat(instance, val, span),
+                                }
+                            }).collect(),
+                        }
+                    },
+                    ConstVal::Variant(var_did) => {
+                        let variant_index = adt_def
+                            .variants
+                            .iter()
+                            .position(|var| var.did == var_did)
+                            .unwrap();
+                        PatternKind::Variant {
+                            adt_def,
+                            substs,
+                            variant_index,
+                            subpatterns: Vec::new(),
+                        }
+                    }
+                    _ => return Pattern {
+                        span,
+                        ty: cv.ty,
+                        kind: Box::new(PatternKind::Constant {
+                            value: cv,
+                        }),
+                    }
+                }
+            },
             ty::TyAdt(adt_def, _) => {
-                if !self.tcx.has_attr(adt_def.did, "structural_match") {
-                    let msg = format!("to use a constant of type `{}` in a pattern, \
-                                       `{}` must be annotated with `#[derive(PartialEq, Eq)]`",
-                                      self.tcx.item_path_str(adt_def.did),
-                                      self.tcx.item_path_str(adt_def.did));
-                    self.tcx.sess.span_err(span, &msg);
+                let struct_var = adt_def.struct_variant();
+                PatternKind::Leaf {
+                    subpatterns: struct_var.fields.iter().enumerate().map(|(i, f)| {
+                        let field = Field::new(i);
+                        let val = match cv.val {
+                            ConstVal::Aggregate(ConstAggregate::Struct(consts)) => {
+                                consts.iter().find(|&&(name, _)| name == f.name).unwrap().1
+                            },
+                            ConstVal::Value(miri) => self.tcx.const_val_field(
+                                self.param_env.and((instance, field, miri, cv.ty)),
+                            ).unwrap(),
+                            _ => bug!("{:#?} is not a valid tuple", cv),
+                        };
+                        FieldPattern {
+                            field,
+                            pattern: self.const_to_pat(instance, val, span),
+                        }
+                    }).collect()
                 }
             }
-            _ => { }
-        }
-        let kind = match expr.node {
-            hir::ExprTup(ref exprs) => {
+            ty::TyTuple(fields, _) => {
                 PatternKind::Leaf {
-                    subpatterns: exprs.iter().enumerate().map(|(i, expr)| {
+                    subpatterns: (0..fields.len()).map(|i| {
+                        let field = Field::new(i);
+                        let val = match cv.val {
+                            ConstVal::Aggregate(ConstAggregate::Tuple(consts)) => consts[i],
+                            ConstVal::Value(miri) => self.tcx.const_val_field(
+                                self.param_env.and((instance, field, miri, cv.ty)),
+                            ).unwrap(),
+                            _ => bug!("{:#?} is not a valid tuple", cv),
+                        };
                         FieldPattern {
-                            field: Field::new(i),
-                            pattern: self.lower_const_expr(expr, pat_id, span)
+                            field,
+                            pattern: self.const_to_pat(instance, val, span),
                         }
                     }).collect()
                 }
             }
-
-            hir::ExprCall(ref callee, ref args) => {
-                let qpath = match callee.node {
-                    hir::ExprPath(ref qpath) => qpath,
-                    _ => bug!()
-                };
-                let ty = self.tables.node_id_to_type(callee.hir_id);
-                let def = self.tables.qpath_def(qpath, callee.hir_id);
-                match def {
-                    Def::Fn(..) | Def::Method(..) => self.lower_lit(expr),
-                    _ => {
-                        let subpatterns = args.iter().enumerate().map(|(i, expr)| {
-                            FieldPattern {
-                                field: Field::new(i),
-                                pattern: self.lower_const_expr(expr, pat_id, span)
-                            }
-                        }).collect();
-                        self.lower_variant_or_leaf(def, ty, subpatterns)
-                    }
+            ty::TyArray(_, n) => {
+                PatternKind::Leaf {
+                    subpatterns: (0..n.val.unwrap_u64()).map(|i| {
+                        let i = i as usize;
+                        let field = Field::new(i);
+                        let val = match cv.val {
+                            ConstVal::Aggregate(ConstAggregate::Array(consts)) => consts[i],
+                            ConstVal::Aggregate(ConstAggregate::Repeat(cv, _)) => cv,
+                            ConstVal::Value(miri) => self.tcx.const_val_field(
+                                self.param_env.and((instance, field, miri, cv.ty)),
+                            ).unwrap(),
+                            _ => bug!("{:#?} is not a valid tuple", cv),
+                        };
+                        FieldPattern {
+                            field,
+                            pattern: self.const_to_pat(instance, val, span),
+                        }
+                    }).collect()
                 }
             }
-
-            hir::ExprStruct(ref qpath, ref fields, None) => {
-                let def = self.tables.qpath_def(qpath, expr.hir_id);
-                let adt_def = match pat_ty.sty {
-                    ty::TyAdt(adt_def, _) => adt_def,
-                    _ => {
-                        span_bug!(
-                            expr.span,
-                            "struct expr without ADT type");
-                    }
-                };
-                let variant_def = adt_def.variant_of_def(def);
-
-                let subpatterns =
-                    fields.iter()
-                          .map(|field| {
-                              let index = variant_def.index_of_field_named(field.name.node);
-                              let index = index.unwrap_or_else(|| {
-                                  span_bug!(
-                                      expr.span,
-                                      "no field with name {:?}",
-                                      field.name);
-                              });
-                              FieldPattern {
-                                  field: Field::new(index),
-                                  pattern: self.lower_const_expr(&field.expr, pat_id, span),
-                              }
-                          })
-                          .collect();
-
-                self.lower_variant_or_leaf(def, pat_ty, subpatterns)
-            }
-
-            hir::ExprArray(ref exprs) => {
-                let pats = exprs.iter()
-                                .map(|expr| self.lower_const_expr(expr, pat_id, span))
-                                .collect();
-                PatternKind::Array {
-                    prefix: pats,
-                    slice: None,
-                    suffix: vec![]
+            _ => {
+                PatternKind::Constant {
+                    value: cv,
                 }
-            }
-
-            hir::ExprPath(ref qpath) => {
-                return self.lower_path(qpath, expr.hir_id, pat_id, span);
-            }
-
-            _ => self.lower_lit(expr)
+            },
         };
 
         Pattern {
             span,
-            ty: pat_ty,
+            ty: cv.ty,
             kind: Box::new(kind),
         }
     }