about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2017-08-04 00:41:44 +0300
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2017-09-11 08:41:03 +0300
commit50076b00c2790a7941772cc97ee371e15b2cb776 (patch)
tree100b84d9c40cf34acfdd5ebc64e488123b41d0df
parente6bce95094facf5bf36afa5995f522d374d00149 (diff)
downloadrust-50076b00c2790a7941772cc97ee371e15b2cb776.tar.gz
rust-50076b00c2790a7941772cc97ee371e15b2cb776.zip
rustc: intern ConstVal's in TyCtxt.
-rw-r--r--src/librustc/hir/mod.rs2
-rw-r--r--src/librustc/ich/impls_ty.rs38
-rw-r--r--src/librustc/middle/const_val.rs54
-rw-r--r--src/librustc/mir/mod.rs15
-rw-r--r--src/librustc/mir/visit.rs4
-rw-r--r--src/librustc/ty/context.rs38
-rw-r--r--src/librustc/ty/mod.rs4
-rw-r--r--src/librustc_const_eval/_match.rs47
-rw-r--r--src/librustc_const_eval/check_match.rs4
-rw-r--r--src/librustc_const_eval/eval.rs142
-rw-r--r--src/librustc_const_eval/pattern.rs59
-rw-r--r--src/librustc_lint/types.rs4
-rw-r--r--src/librustc_metadata/decoder.rs15
-rw-r--r--src/librustc_mir/build/expr/as_rvalue.rs10
-rw-r--r--src/librustc_mir/build/matches/mod.rs6
-rw-r--r--src/librustc_mir/build/matches/test.rs38
-rw-r--r--src/librustc_mir/build/misc.rs14
-rw-r--r--src/librustc_mir/build/mod.rs6
-rw-r--r--src/librustc_mir/hair/cx/block.rs5
-rw-r--r--src/librustc_mir/hair/cx/expr.rs13
-rw-r--r--src/librustc_mir/hair/cx/mod.rs28
-rw-r--r--src/librustc_mir/shim.rs8
-rw-r--r--src/librustc_mir/transform/elaborate_drops.rs4
-rw-r--r--src/librustc_mir/transform/generator.rs6
-rw-r--r--src/librustc_mir/transform/simplify_branches.rs2
-rw-r--r--src/librustc_mir/transform/type_check.rs2
-rw-r--r--src/librustc_mir/util/elaborate_drops.rs4
-rw-r--r--src/librustc_passes/mir_stats.rs2
-rw-r--r--src/librustc_trans/mir/analyze.rs2
-rw-r--r--src/librustc_trans/mir/constant.rs9
-rw-r--r--src/librustc_typeck/collect.rs2
31 files changed, 347 insertions, 240 deletions
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index d254d50e8bd..dd2a3978d88 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -611,7 +611,7 @@ pub enum BindingAnnotation {
   RefMut,
 }
 
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum RangeEnd {
     Included,
     Excluded,
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index 077905b3ac0..0d8aead0b36 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -16,7 +16,6 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
                                            StableHasherResult};
 use std::hash as std_hash;
 use std::mem;
-use syntax_pos::symbol::InternedString;
 use middle::region;
 use ty;
 
@@ -272,52 +271,49 @@ for ::middle::const_val::ConstVal<'gcx> {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
                                           hasher: &mut StableHasher<W>) {
-        use middle::const_val::ConstVal;
+        use middle::const_val::ConstVal::*;
+        use middle::const_val::ConstAggregate::*;
 
         mem::discriminant(self).hash_stable(hcx, hasher);
 
         match *self {
-            ConstVal::Float(ref value) => {
+            Float(ref value) => {
                 value.hash_stable(hcx, hasher);
             }
-            ConstVal::Integral(ref value) => {
+            Integral(ref value) => {
                 value.hash_stable(hcx, hasher);
             }
-            ConstVal::Str(ref value) => {
+            Str(ref value) => {
                 value.hash_stable(hcx, hasher);
             }
-            ConstVal::ByteStr(ref value) => {
+            ByteStr(ref value) => {
                 value.hash_stable(hcx, hasher);
             }
-            ConstVal::Bool(value) => {
+            Bool(value) => {
                 value.hash_stable(hcx, hasher);
             }
-            ConstVal::Char(value) => {
+            Char(value) => {
                 value.hash_stable(hcx, hasher);
             }
-            ConstVal::Variant(def_id) => {
+            Variant(def_id) => {
                 def_id.hash_stable(hcx, hasher);
             }
-            ConstVal::Function(def_id, substs) => {
+            Function(def_id, substs) => {
                 def_id.hash_stable(hcx, hasher);
                 substs.hash_stable(hcx, hasher);
             }
-            ConstVal::Struct(ref name_value_map) => {
-                let mut values: Vec<(InternedString, &ConstVal)> =
-                    name_value_map.iter()
-                                  .map(|(name, val)| (name.as_str(), val))
-                                  .collect();
-
+            Aggregate(Struct(ref name_values)) => {
+                let mut values = name_values.to_vec();
                 values.sort_unstable_by_key(|&(ref name, _)| name.clone());
                 values.hash_stable(hcx, hasher);
             }
-            ConstVal::Tuple(ref value) => {
+            Aggregate(Tuple(ref value)) => {
                 value.hash_stable(hcx, hasher);
             }
-            ConstVal::Array(ref value) => {
+            Aggregate(Array(ref value)) => {
                 value.hash_stable(hcx, hasher);
             }
-            ConstVal::Repeat(ref value, times) => {
+            Aggregate(Repeat(ref value, times)) => {
                 value.hash_stable(hcx, hasher);
                 times.hash_stable(hcx, hasher);
             }
@@ -325,6 +321,10 @@ for ::middle::const_val::ConstVal<'gcx> {
     }
 }
 
+impl_stable_hash_for!(struct ::middle::const_val::ByteArray<'tcx> {
+    data
+});
+
 impl_stable_hash_for!(struct ty::ClosureSubsts<'tcx> { substs });
 
 impl_stable_hash_for!(struct ty::GeneratorInterior<'tcx> { witness });
diff --git a/src/librustc/middle/const_val.rs b/src/librustc/middle/const_val.rs
index b6b1648f396..8eac44966bb 100644
--- a/src/librustc/middle/const_val.rs
+++ b/src/librustc/middle/const_val.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use self::ConstVal::*;
+use self::ConstAggregate::*;
 pub use rustc_const_math::ConstInt;
 
 use hir;
@@ -22,30 +23,55 @@ use rustc_const_math::*;
 
 use graphviz::IntoCow;
 use errors::DiagnosticBuilder;
+use serialize::{self, Encodable, Encoder, Decodable, Decoder};
 use syntax::symbol::InternedString;
 use syntax::ast;
 use syntax_pos::Span;
 
 use std::borrow::Cow;
-use std::collections::BTreeMap;
-use std::rc::Rc;
 
-pub type EvalResult<'tcx> = Result<ConstVal<'tcx>, ConstEvalErr<'tcx>>;
+pub type EvalResult<'tcx> = Result<&'tcx ConstVal<'tcx>, ConstEvalErr<'tcx>>;
 
-#[derive(Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq)]
+#[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable, Eq, PartialEq)]
 pub enum ConstVal<'tcx> {
     Float(ConstFloat),
     Integral(ConstInt),
     Str(InternedString),
-    ByteStr(Rc<Vec<u8>>),
+    ByteStr(ByteArray<'tcx>),
     Bool(bool),
     Char(char),
     Variant(DefId),
     Function(DefId, &'tcx Substs<'tcx>),
-    Struct(BTreeMap<ast::Name, ConstVal<'tcx>>),
-    Tuple(Vec<ConstVal<'tcx>>),
-    Array(Vec<ConstVal<'tcx>>),
-    Repeat(Box<ConstVal<'tcx>>, u64),
+    Aggregate(ConstAggregate<'tcx>),
+}
+
+impl<'tcx> serialize::UseSpecializedDecodable for &'tcx ConstVal<'tcx> {}
+
+#[derive(Copy, Clone, Debug, Hash, RustcEncodable, Eq, PartialEq)]
+pub struct ByteArray<'tcx> {
+    pub data: &'tcx [u8],
+}
+
+impl<'tcx> serialize::UseSpecializedDecodable for ByteArray<'tcx> {}
+
+#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
+pub enum ConstAggregate<'tcx> {
+    Struct(&'tcx [(ast::Name, &'tcx ConstVal<'tcx>)]),
+    Tuple(&'tcx [&'tcx ConstVal<'tcx>]),
+    Array(&'tcx [&'tcx ConstVal<'tcx>]),
+    Repeat(&'tcx ConstVal<'tcx>, u64),
+}
+
+impl<'tcx> Encodable for ConstAggregate<'tcx> {
+    fn encode<S: Encoder>(&self, _: &mut S) -> Result<(), S::Error> {
+        bug!("should never encode ConstAggregate::{:?}", self)
+    }
+}
+
+impl<'tcx> Decodable for ConstAggregate<'tcx> {
+    fn decode<D: Decoder>(_: &mut D) -> Result<Self, D::Error> {
+        bug!("should never decode ConstAggregate")
+    }
 }
 
 impl<'tcx> ConstVal<'tcx> {
@@ -58,11 +84,11 @@ impl<'tcx> ConstVal<'tcx> {
             Bool(_) => "boolean",
             Char(..) => "char",
             Variant(_) => "enum variant",
-            Struct(_) => "struct",
-            Tuple(_) => "tuple",
+            Aggregate(Struct(_)) => "struct",
+            Aggregate(Tuple(_)) => "tuple",
             Function(..) => "function definition",
-            Array(..) => "array",
-            Repeat(..) => "repeat",
+            Aggregate(Array(..)) => "array",
+            Aggregate(Repeat(..)) => "repeat",
         }
     }
 
@@ -233,7 +259,7 @@ pub fn eval_length(tcx: TyCtxt,
     let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
     let substs = Substs::identity_for_item(tcx.global_tcx(), count_def_id);
     match tcx.at(count_expr.span).const_eval(param_env.and((count_def_id, substs))) {
-        Ok(Integral(Usize(count))) => {
+        Ok(&Integral(Usize(count))) => {
             let val = count.as_u64(tcx.sess.target.uint_type);
             assert_eq!(val as usize as u64, val);
             Ok(val as usize)
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index e63162c68c0..a7c4e529d24 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -1190,7 +1190,9 @@ impl<'tcx> Operand<'tcx> {
         Operand::Constant(box Constant {
             span,
             ty: tcx.type_of(def_id).subst(tcx, substs),
-            literal: Literal::Value { value: ConstVal::Function(def_id, substs) },
+            literal: Literal::Value {
+                value: tcx.mk_const(ConstVal::Function(def_id, substs))
+            },
         })
     }
 
@@ -1478,7 +1480,7 @@ pub enum Literal<'tcx> {
         substs: &'tcx Substs<'tcx>,
     },
     Value {
-        value: ConstVal<'tcx>,
+        value: &'tcx ConstVal<'tcx>,
     },
     Promoted {
         // Index into the `promoted` vector of `Mir`.
@@ -1516,9 +1518,9 @@ fn fmt_const_val<W: Write>(fmt: &mut W, const_val: &ConstVal) -> fmt::Result {
     match *const_val {
         Float(f) => write!(fmt, "{:?}", f),
         Integral(n) => write!(fmt, "{}", n),
-        Str(ref s) => write!(fmt, "{:?}", s),
-        ByteStr(ref bytes) => {
-            let escaped: String = bytes
+        Str(s) => write!(fmt, "{:?}", s),
+        ByteStr(bytes) => {
+            let escaped: String = bytes.data
                 .iter()
                 .flat_map(|&ch| ascii::escape_default(ch).map(|c| c as char))
                 .collect();
@@ -1528,8 +1530,7 @@ fn fmt_const_val<W: Write>(fmt: &mut W, const_val: &ConstVal) -> fmt::Result {
         Char(c) => write!(fmt, "{:?}", c),
         Variant(def_id) |
         Function(def_id, _) => write!(fmt, "{}", item_path_str(def_id)),
-        Struct(_) | Tuple(_) | Array(_) | Repeat(..) =>
-            bug!("ConstVal `{:?}` should not be in MIR", const_val),
+        Aggregate(_) => bug!("`ConstVal::{:?}` should not be in MIR", const_val),
     }
 }
 
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index f26505c6d02..d2719224e37 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -233,7 +233,7 @@ macro_rules! make_mir_visitor {
             }
 
             fn visit_const_val(&mut self,
-                               const_val: & $($mutability)* ConstVal,
+                               const_val: & $($mutability)* &'tcx ConstVal<'tcx>,
                                _: Location) {
                 self.super_const_val(const_val);
             }
@@ -760,7 +760,7 @@ macro_rules! make_mir_visitor {
                                     _substs: & $($mutability)* ClosureSubsts<'tcx>) {
             }
 
-            fn super_const_val(&mut self, _const_val: & $($mutability)* ConstVal) {
+            fn super_const_val(&mut self, _const_val: & $($mutability)* &'tcx ConstVal<'tcx>) {
             }
 
             fn super_const_int(&mut self, _const_int: &ConstInt) {
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 2a0dc455f47..5d15e3a8cab 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -21,6 +21,7 @@ use hir::map as hir_map;
 use hir::map::DefPathHash;
 use lint::{self, Lint};
 use ich::{self, StableHashingContext, NodeIdHashingMode};
+use middle::const_val::ConstVal;
 use middle::free_region::FreeRegionMap;
 use middle::lang_items;
 use middle::resolve_lifetime::{self, ObjectLifetimeDefault};
@@ -108,6 +109,7 @@ pub struct CtxtInterners<'tcx> {
     region: RefCell<FxHashSet<Interned<'tcx, RegionKind>>>,
     existential_predicates: RefCell<FxHashSet<Interned<'tcx, Slice<ExistentialPredicate<'tcx>>>>>,
     predicates: RefCell<FxHashSet<Interned<'tcx, Slice<Predicate<'tcx>>>>>,
+    const_: RefCell<FxHashSet<Interned<'tcx, ConstVal<'tcx>>>>,
 }
 
 impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
@@ -120,6 +122,7 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
             region: RefCell::new(FxHashSet()),
             existential_predicates: RefCell::new(FxHashSet()),
             predicates: RefCell::new(FxHashSet()),
+            const_: RefCell::new(FxHashSet()),
         }
     }
 
@@ -934,6 +937,32 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         self.global_arenas.adt_def.alloc(def)
     }
 
+    pub fn alloc_byte_array(self, bytes: &[u8]) -> &'gcx [u8] {
+        if bytes.is_empty() {
+            &[]
+        } else {
+            self.global_interners.arena.alloc_slice(bytes)
+        }
+    }
+
+    pub fn alloc_constval_slice(self, values: &[&'tcx ConstVal<'gcx>])
+                                -> &'gcx [&'tcx ConstVal<'gcx>] {
+        if values.is_empty() {
+            &[]
+        } else {
+            self.global_interners.arena.alloc_slice(values)
+        }
+    }
+
+    pub fn alloc_name_constval_slice(self, values: &[(ast::Name, &'tcx ConstVal<'gcx>)])
+                                     -> &'gcx [(ast::Name, &'tcx ConstVal<'gcx>)] {
+        if values.is_empty() {
+            &[]
+        } else {
+            self.global_interners.arena.alloc_slice(values)
+        }
+    }
+
     pub fn intern_stability(self, stab: attr::Stability) -> &'gcx attr::Stability {
         if let Some(st) = self.stability_interner.borrow().get(&stab) {
             return st;
@@ -1507,6 +1536,12 @@ impl<'tcx: 'lcx, 'lcx> Borrow<[Predicate<'lcx>]>
     }
 }
 
+impl<'tcx: 'lcx, 'lcx> Borrow<ConstVal<'lcx>> for Interned<'tcx, ConstVal<'tcx>> {
+    fn borrow<'a>(&'a self) -> &'a ConstVal<'lcx> {
+        &self.0
+    }
+}
+
 macro_rules! intern_method {
     ($lt_tcx:tt, $name:ident: $method:ident($alloc:ty,
                                             $alloc_method:ident,
@@ -1587,7 +1622,8 @@ direct_interners!('tcx,
             &ty::ReVar(_) | &ty::ReSkolemized(..) => true,
             _ => false
         }
-    }) -> RegionKind
+    }) -> RegionKind,
+    const_: mk_const(/*|c: &Const| keep_local(&c.ty)*/ |_| false) -> ConstVal<'tcx>
 );
 
 macro_rules! slice_interners {
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 8b7ae79f151..9be12195952 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -1601,7 +1601,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
             if let VariantDiscr::Explicit(expr_did) = v.discr {
                 let substs = Substs::identity_for_item(tcx.global_tcx(), expr_did);
                 match tcx.const_eval(param_env.and((expr_did, substs))) {
-                    Ok(ConstVal::Integral(v)) => {
+                    Ok(&ConstVal::Integral(v)) => {
                         discr = v;
                     }
                     err => {
@@ -1641,7 +1641,7 @@ impl<'a, 'gcx, 'tcx> AdtDef {
                 ty::VariantDiscr::Explicit(expr_did) => {
                     let substs = Substs::identity_for_item(tcx.global_tcx(), expr_did);
                     match tcx.const_eval(param_env.and((expr_did, substs))) {
-                        Ok(ConstVal::Integral(v)) => {
+                        Ok(&ConstVal::Integral(v)) => {
                             explicit_value = v;
                             break;
                         }
diff --git a/src/librustc_const_eval/_match.rs b/src/librustc_const_eval/_match.rs
index bc9aa9665c1..aea1f454d81 100644
--- a/src/librustc_const_eval/_match.rs
+++ b/src/librustc_const_eval/_match.rs
@@ -182,13 +182,13 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
         self.byte_array_map.entry(pat).or_insert_with(|| {
             match pat.kind {
                 box PatternKind::Constant {
-                    value: ConstVal::ByteStr(ref data)
+                    value: &ConstVal::ByteStr(b)
                 } => {
-                    data.iter().map(|c| &*pattern_arena.alloc(Pattern {
+                    b.data.iter().map(|&b| &*pattern_arena.alloc(Pattern {
                         ty: tcx.types.u8,
                         span: pat.span,
                         kind: box PatternKind::Constant {
-                            value: ConstVal::Integral(ConstInt::U8(*c))
+                            value: tcx.mk_const(ConstVal::Integral(ConstInt::U8(b)))
                         }
                     })).collect()
                 }
@@ -228,9 +228,9 @@ pub enum Constructor<'tcx> {
     /// Enum variants.
     Variant(DefId),
     /// Literal values.
-    ConstantValue(ConstVal<'tcx>),
+    ConstantValue(&'tcx ConstVal<'tcx>),
     /// Ranges of literal values (`2...5` and `2..5`).
-    ConstantRange(ConstVal<'tcx>, ConstVal<'tcx>, RangeEnd),
+    ConstantRange(&'tcx ConstVal<'tcx>, &'tcx ConstVal<'tcx>, RangeEnd),
     /// Array patterns of length n.
     Slice(usize),
 }
@@ -370,7 +370,7 @@ impl<'tcx> Witness<'tcx> {
 
                 _ => {
                     match *ctor {
-                        ConstantValue(ref v) => PatternKind::Constant { value: v.clone() },
+                        ConstantValue(value) => PatternKind::Constant { value },
                         _ => PatternKind::Wild,
                     }
                 }
@@ -404,8 +404,11 @@ fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
 {
     debug!("all_constructors({:?})", pcx.ty);
     match pcx.ty.sty {
-        ty::TyBool =>
-            [true, false].iter().map(|b| ConstantValue(ConstVal::Bool(*b))).collect(),
+        ty::TyBool => {
+            [true, false].iter().map(|&b| {
+                ConstantValue(cx.tcx.mk_const(ConstVal::Bool(b)))
+            }).collect()
+        }
         ty::TySlice(ref sub_ty) => {
             if cx.is_uninhabited(sub_ty) {
                 vec![Slice(0)]
@@ -511,8 +514,8 @@ fn max_slice_length<'p, 'a: 'p, 'tcx: 'a, I>(
 
     for row in patterns {
         match *row.kind {
-            PatternKind::Constant { value: ConstVal::ByteStr(ref data) } => {
-                max_fixed_len = cmp::max(max_fixed_len, data.len());
+            PatternKind::Constant { value: &ConstVal::ByteStr(b) } => {
+                max_fixed_len = cmp::max(max_fixed_len, b.data.len());
             }
             PatternKind::Slice { ref prefix, slice: None, ref suffix } => {
                 let fixed_len = prefix.len() + suffix.len();
@@ -715,10 +718,10 @@ fn pat_constructors<'tcx>(_cx: &mut MatchCheckCtxt,
             Some(vec![Single]),
         PatternKind::Variant { adt_def, variant_index, .. } =>
             Some(vec![Variant(adt_def.variants[variant_index].did)]),
-        PatternKind::Constant { ref value } =>
-            Some(vec![ConstantValue(value.clone())]),
-        PatternKind::Range { ref lo, ref hi, ref end } =>
-            Some(vec![ConstantRange(lo.clone(), hi.clone(), end.clone())]),
+        PatternKind::Constant { value } =>
+            Some(vec![ConstantValue(value)]),
+        PatternKind::Range { lo, hi, end } =>
+            Some(vec![ConstantRange(lo, hi, end)]),
         PatternKind::Array { .. } => match pcx.ty.sty {
             ty::TyArray(_, length) => Some(vec![Slice(length)]),
             _ => span_bug!(pat.span, "bad ty {:?} for array pattern", pcx.ty)
@@ -806,7 +809,7 @@ fn slice_pat_covered_by_constructor(_tcx: TyCtxt, _span: Span,
                                     suffix: &[Pattern])
                                     -> Result<bool, ErrorReported> {
     let data = match *ctor {
-        ConstantValue(ConstVal::ByteStr(ref data)) => data,
+        ConstantValue(&ConstVal::ByteStr(b)) => b.data,
         _ => bug!()
     };
 
@@ -820,7 +823,7 @@ fn slice_pat_covered_by_constructor(_tcx: TyCtxt, _span: Span,
             data[data.len()-suffix.len()..].iter().zip(suffix))
     {
         match pat.kind {
-            box PatternKind::Constant { ref value } => match *value {
+            box PatternKind::Constant { value } => match *value {
                 ConstVal::Integral(ConstInt::U8(u)) => {
                     if u != *ch {
                         return Ok(false);
@@ -843,19 +846,19 @@ fn constructor_covered_by_range(tcx: TyCtxt, span: Span,
     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);
     match *ctor {
-        ConstantValue(ref value) => {
+        ConstantValue(value) => {
             let to = cmp_to(value)?;
             let end = (to == Ordering::Less) ||
                       (end == RangeEnd::Included && to == Ordering::Equal);
             Ok(cmp_from(value)? && end)
         },
-        ConstantRange(ref from, ref to, RangeEnd::Included) => {
+        ConstantRange(from, to, RangeEnd::Included) => {
             let to = cmp_to(to)?;
             let end = (to == Ordering::Less) ||
                       (end == RangeEnd::Included && to == Ordering::Equal);
             Ok(cmp_from(from)? && end)
         },
-        ConstantRange(ref from, ref to, RangeEnd::Excluded) => {
+        ConstantRange(from, to, RangeEnd::Excluded) => {
             let to = cmp_to(to)?;
             let end = (to == Ordering::Less) ||
                       (end == RangeEnd::Excluded && to == Ordering::Equal);
@@ -919,11 +922,11 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
             Some(vec![subpattern])
         }
 
-        PatternKind::Constant { ref value } => {
+        PatternKind::Constant { value } => {
             match *constructor {
                 Slice(..) => match *value {
-                    ConstVal::ByteStr(ref data) => {
-                        if wild_patterns.len() == data.len() {
+                    ConstVal::ByteStr(b) => {
+                        if wild_patterns.len() == b.data.len() {
                             Some(cx.lower_byte_str_pattern(pat))
                         } else {
                             None
diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs
index d832ad0ab1d..0339969f2b4 100644
--- a/src/librustc_const_eval/check_match.rs
+++ b/src/librustc_const_eval/check_match.rs
@@ -140,7 +140,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
     fn check_match(
         &self,
         scrut: &hir::Expr,
-        arms: &[hir::Arm],
+        arms: &'tcx [hir::Arm],
         source: hir::MatchSource)
     {
         for arm in arms {
@@ -231,7 +231,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
         }
     }
 
-    fn check_irrefutable(&self, pat: &Pat, origin: &str) {
+    fn check_irrefutable(&self, pat: &'tcx Pat, origin: &str) {
         let module = self.tcx.hir.get_module_parent(pat.id);
         MatchCheckCtxt::create_and_enter(self.tcx, module, |ref mut cx| {
             let mut patcx = PatternContext::new(self.tcx,
diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs
index c71c121ca50..5f0a0702291 100644
--- a/src/librustc_const_eval/eval.rs
+++ b/src/librustc_const_eval/eval.rs
@@ -9,8 +9,9 @@
 // except according to those terms.
 
 use rustc::middle::const_val::ConstVal::*;
+use rustc::middle::const_val::ConstAggregate::*;
 use rustc::middle::const_val::ErrKind::*;
-use rustc::middle::const_val::{ConstVal, ConstEvalErr, EvalResult, ErrKind};
+use rustc::middle::const_val::{ByteArray, ConstVal, ConstEvalErr, EvalResult, ErrKind};
 
 use rustc::hir::map as hir_map;
 use rustc::hir::map::blocks::FnLikeNode;
@@ -88,7 +89,7 @@ pub struct ConstContext<'a, 'tcx: 'a> {
     tables: &'a ty::TypeckTables<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     substs: &'tcx Substs<'tcx>,
-    fn_args: Option<NodeMap<ConstVal<'tcx>>>
+    fn_args: Option<NodeMap<&'tcx ConstVal<'tcx>>>
 }
 
 impl<'a, 'tcx> ConstContext<'a, 'tcx> {
@@ -107,7 +108,7 @@ impl<'a, 'tcx> ConstContext<'a, 'tcx> {
 
     /// Evaluate a constant expression in a context where the expression isn't
     /// guaranteed to be evaluable.
-    pub fn eval(&self, e: &Expr) -> EvalResult<'tcx> {
+    pub fn eval(&self, e: &'tcx Expr) -> EvalResult<'tcx> {
         if self.tables.tainted_by_errors {
             signal!(e, TypeckError);
         }
@@ -118,7 +119,7 @@ impl<'a, 'tcx> ConstContext<'a, 'tcx> {
 type CastResult<'tcx> = Result<ConstVal<'tcx>, ErrKind<'tcx>>;
 
 fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
-                                     e: &Expr) -> EvalResult<'tcx> {
+                                     e: &'tcx Expr) -> EvalResult<'tcx> {
     let tcx = cx.tcx;
     let ety = cx.tables.expr_ty(e).subst(tcx, cx.substs);
 
@@ -133,57 +134,66 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
             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;
-            match (&lit.node, &ety.sty) {
+            let negated = match (&lit.node, &ety.sty) {
                 (&LitKind::Int(I8_OVERFLOW, _), &ty::TyInt(IntTy::I8)) |
                 (&LitKind::Int(I8_OVERFLOW, Signed(IntTy::I8)), _) => {
-                    return Ok(Integral(I8(i8::min_value())))
+                    Some(I8(i8::min_value()))
                 },
                 (&LitKind::Int(I16_OVERFLOW, _), &ty::TyInt(IntTy::I16)) |
                 (&LitKind::Int(I16_OVERFLOW, Signed(IntTy::I16)), _) => {
-                    return Ok(Integral(I16(i16::min_value())))
+                    Some(I16(i16::min_value()))
                 },
                 (&LitKind::Int(I32_OVERFLOW, _), &ty::TyInt(IntTy::I32)) |
                 (&LitKind::Int(I32_OVERFLOW, Signed(IntTy::I32)), _) => {
-                    return Ok(Integral(I32(i32::min_value())))
+                    Some(I32(i32::min_value()))
                 },
                 (&LitKind::Int(I64_OVERFLOW, _), &ty::TyInt(IntTy::I64)) |
                 (&LitKind::Int(I64_OVERFLOW, Signed(IntTy::I64)), _) => {
-                    return Ok(Integral(I64(i64::min_value())))
+                    Some(I64(i64::min_value()))
                 },
                 (&LitKind::Int(I128_OVERFLOW, _), &ty::TyInt(IntTy::I128)) |
                 (&LitKind::Int(I128_OVERFLOW, Signed(IntTy::I128)), _) => {
-                    return Ok(Integral(I128(i128::min_value())))
+                    Some(I128(i128::min_value()))
                 },
                 (&LitKind::Int(n, _), &ty::TyInt(IntTy::Is)) |
                 (&LitKind::Int(n, Signed(IntTy::Is)), _) => {
                     match tcx.sess.target.int_type {
                         IntTy::I16 => if n == I16_OVERFLOW {
-                            return Ok(Integral(Isize(Is16(i16::min_value()))));
+                            Some(Isize(Is16(i16::min_value())))
+                        } else {
+                            None
                         },
                         IntTy::I32 => if n == I32_OVERFLOW {
-                            return Ok(Integral(Isize(Is32(i32::min_value()))));
+                            Some(Isize(Is32(i32::min_value())))
+                        } else {
+                            None
                         },
                         IntTy::I64 => if n == I64_OVERFLOW {
-                            return Ok(Integral(Isize(Is64(i64::min_value()))));
+                            Some(Isize(Is64(i64::min_value())))
+                        } else {
+                            None
                         },
                         _ => span_bug!(e.span, "typeck error")
                     }
                 },
-                _ => {},
+                _ => None
+            };
+            if let Some(i) = negated {
+                return Ok(tcx.mk_const(Integral(i)));
             }
         }
-        match cx.eval(inner)? {
+        tcx.mk_const(match *cx.eval(inner)? {
           Float(f) => Float(-f),
           Integral(i) => Integral(math!(e, -i)),
           const_val => signal!(e, NegateOn(const_val)),
-        }
+        })
       }
       hir::ExprUnary(hir::UnNot, ref inner) => {
-        match cx.eval(inner)? {
+        tcx.mk_const(match *cx.eval(inner)? {
           Integral(i) => Integral(math!(e, !i)),
           Bool(b) => Bool(!b),
           const_val => signal!(e, NotOn(const_val)),
-        }
+        })
       }
       hir::ExprUnary(hir::UnDeref, _) => signal!(e, UnimplementedConstVal("deref operation")),
       hir::ExprBinary(op, ref a, ref b) => {
@@ -191,7 +201,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
         // gives us a type through a type-suffix, cast or const def type
         // we need to re-eval the other value of the BinOp if it was
         // not inferred
-        match (cx.eval(a)?, cx.eval(b)?) {
+        tcx.mk_const(match (*cx.eval(a)?, *cx.eval(b)?) {
           (Float(a), Float(b)) => {
             use std::cmp::Ordering::*;
             match op.node {
@@ -260,7 +270,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
           }
 
           _ => signal!(e, MiscBinaryOp),
-        }
+        })
       }
       hir::ExprCast(ref base, _) => {
         let base_val = cx.eval(base)?;
@@ -268,8 +278,8 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
         if ety == base_ty {
             base_val
         } else {
-            match cast_const(tcx, base_val, ety) {
-                Ok(val) => val,
+            match cast_const(tcx, *base_val, ety) {
+                Ok(val) => tcx.mk_const(val),
                 Err(kind) => signal!(e, kind),
             }
         }
@@ -291,32 +301,32 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
                     }
               },
               Def::VariantCtor(variant_def, CtorKind::Const) => {
-                Variant(variant_def)
+                tcx.mk_const(Variant(variant_def))
               }
               Def::VariantCtor(_, CtorKind::Fn) => {
                   signal!(e, UnimplementedConstVal("enum variants"));
               }
               Def::StructCtor(_, CtorKind::Const) => {
-                  ConstVal::Struct(Default::default())
+                  tcx.mk_const(Aggregate(Struct(&[])))
               }
               Def::StructCtor(_, CtorKind::Fn) => {
                   signal!(e, UnimplementedConstVal("tuple struct constructors"))
               }
               Def::Local(id) => {
                   debug!("Def::Local({:?}): {:?}", id, cx.fn_args);
-                  if let Some(val) = cx.fn_args.as_ref().and_then(|args| args.get(&id)) {
-                      val.clone()
+                  if let Some(&val) = cx.fn_args.as_ref().and_then(|args| args.get(&id)) {
+                      val
                   } else {
                       signal!(e, NonConstPath);
                   }
               },
-              Def::Method(id) | Def::Fn(id) => Function(id, substs),
+              Def::Method(id) | Def::Fn(id) => tcx.mk_const(Function(id, substs)),
               Def::Err => span_bug!(e.span, "typeck error"),
               _ => signal!(e, NonConstPath),
           }
       }
       hir::ExprCall(ref callee, ref args) => {
-          let (def_id, substs) = match cx.eval(callee)? {
+          let (def_id, substs) = match *cx.eval(callee)? {
               Function(def_id, substs) => (def_id, substs),
               _ => signal!(e, TypeckError),
           };
@@ -329,14 +339,14 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
             };
             match &tcx.item_name(def_id)[..] {
                 "size_of" => {
-                    let size = layout_of(substs.type_at(0))?.size(tcx);
-                    return Ok(Integral(Usize(ConstUsize::new(size.bytes(),
-                        tcx.sess.target.uint_type).unwrap())));
+                    let size = layout_of(substs.type_at(0))?.size(tcx).bytes();
+                    return Ok(tcx.mk_const(Integral(Usize(ConstUsize::new(size,
+                        tcx.sess.target.uint_type).unwrap()))));
                 }
                 "min_align_of" => {
-                    let align = layout_of(substs.type_at(0))?.align(tcx);
-                    return Ok(Integral(Usize(ConstUsize::new(align.abi(),
-                        tcx.sess.target.uint_type).unwrap())));
+                    let align = layout_of(substs.type_at(0))?.align(tcx).abi();
+                    return Ok(tcx.mk_const(Integral(Usize(ConstUsize::new(align,
+                        tcx.sess.target.uint_type).unwrap()))));
                 }
                 _ => signal!(e, TypeckError)
             }
@@ -385,38 +395,39 @@ 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, ety) {
-          Ok(val) => val,
+          Ok(val) => tcx.mk_const(val),
           Err(err) => signal!(e, err),
       },
       hir::ExprBlock(ref block) => {
         match block.expr {
             Some(ref expr) => cx.eval(expr)?,
-            None => Tuple(vec![]),
+            None => tcx.mk_const(Aggregate(Tuple(&[]))),
         }
       }
       hir::ExprType(ref e, _) => cx.eval(e)?,
       hir::ExprTup(ref fields) => {
-        Tuple(fields.iter().map(|e| cx.eval(e)).collect::<Result<_, _>>()?)
+        let values = fields.iter().map(|e| cx.eval(e)).collect::<Result<Vec<_>, _>>()?;
+        tcx.mk_const(Aggregate(Tuple(tcx.alloc_constval_slice(&values))))
       }
       hir::ExprStruct(_, ref fields, _) => {
-        Struct(fields.iter().map(|f| {
+        tcx.mk_const(Aggregate(Struct(tcx.alloc_name_constval_slice(&fields.iter().map(|f| {
             cx.eval(&f.expr).map(|v| (f.name.node, v))
-        }).collect::<Result<_, _>>()?)
+        }).collect::<Result<Vec<_>, _>>()?))))
       }
       hir::ExprIndex(ref arr, ref idx) => {
         if !tcx.sess.features.borrow().const_indexing {
             signal!(e, IndexOpFeatureGated);
         }
         let arr = cx.eval(arr)?;
-        let idx = match cx.eval(idx)? {
+        let idx = match *cx.eval(idx)? {
             Integral(Usize(i)) => i.as_u64(tcx.sess.target.uint_type),
             _ => signal!(idx, IndexNotUsize),
         };
         assert_eq!(idx as usize as u64, idx);
-        match arr {
-            Array(ref v) => {
-                if let Some(elem) = v.get(idx as usize) {
-                    elem.clone()
+        match *arr {
+            Aggregate(Array(v)) => {
+                if let Some(&elem) = v.get(idx as usize) {
+                    elem
                 } else {
                     let n = v.len() as u64;
                     assert_eq!(n as usize as u64, n);
@@ -424,44 +435,43 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>,
                 }
             }
 
-            Repeat(.., n) if idx >= n => {
+            Aggregate(Repeat(.., n)) if idx >= n => {
                 signal!(e, IndexOutOfBounds { len: n, index: idx })
             }
-            Repeat(ref elem, _) => (**elem).clone(),
+            Aggregate(Repeat(elem, _)) => elem,
 
-            ByteStr(ref data) if idx >= data.len() as u64 => {
-                signal!(e, IndexOutOfBounds { len: data.len() as u64, index: idx })
+            ByteStr(b) if idx >= b.data.len() as u64 => {
+                signal!(e, IndexOutOfBounds { len: b.data.len() as u64, index: idx })
             }
-            ByteStr(data) => {
-                Integral(U8(data[idx as usize]))
+            ByteStr(b) => {
+                tcx.mk_const(Integral(U8(b.data[idx as usize])))
             },
 
             _ => signal!(e, IndexedNonVec),
         }
       }
       hir::ExprArray(ref v) => {
-        Array(v.iter().map(|e| cx.eval(e)).collect::<Result<_, _>>()?)
+        let values = v.iter().map(|e| cx.eval(e)).collect::<Result<Vec<_>, _>>()?;
+        tcx.mk_const(Aggregate(Array(tcx.alloc_constval_slice(&values))))
       }
       hir::ExprRepeat(ref elem, _) => {
           let n = match ety.sty {
             ty::TyArray(_, n) => n as u64,
             _ => span_bug!(e.span, "typeck error")
           };
-          Repeat(Box::new(cx.eval(elem)?), n)
+          tcx.mk_const(Aggregate(Repeat(cx.eval(elem)?, n)))
       },
       hir::ExprTupField(ref base, index) => {
-        let c = cx.eval(base)?;
-        if let Tuple(ref fields) = c {
-            fields[index.node].clone()
+        if let Aggregate(Tuple(fields)) = *cx.eval(base)? {
+            fields[index.node]
         } else {
             signal!(base, ExpectedConstTuple);
         }
       }
       hir::ExprField(ref base, field_name) => {
-        let c = cx.eval(base)?;
-        if let Struct(ref fields) = c {
-            if let Some(f) = fields.get(&field_name.node) {
-                f.clone()
+        if let Aggregate(Struct(fields)) = *cx.eval(base)? {
+            if let Some(&(_, f)) = fields.iter().find(|&&(name, _)| name == field_name.node) {
+                f
             } else {
                 signal!(e, MissingStructField);
             }
@@ -625,7 +635,7 @@ fn cast_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 Err(ErrKind::UnimplementedConstVal("casting a bytestr to a raw ptr"))
             },
             ty::TyRef(_, ty::TypeAndMut { ref ty, mutbl: hir::MutImmutable }) => match ty.sty {
-                ty::TyArray(ty, n) if ty == tcx.types.u8 && n == b.len() => Ok(ByteStr(b)),
+                ty::TyArray(ty, n) if ty == tcx.types.u8 && n == b.data.len() => Ok(val),
                 ty::TySlice(_) => {
                     Err(ErrKind::UnimplementedConstVal("casting a bytestr to slice"))
                 },
@@ -645,7 +655,7 @@ fn cast_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 }
 
-fn lit_to_const<'a, 'tcx>(lit: &ast::LitKind,
+fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind,
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           mut ty: Ty<'tcx>)
                           -> Result<ConstVal<'tcx>, ErrKind<'tcx>> {
@@ -660,7 +670,7 @@ fn lit_to_const<'a, 'tcx>(lit: &ast::LitKind,
 
     match *lit {
         LitKind::Str(ref s, _) => Ok(Str(s.as_str())),
-        LitKind::ByteStr(ref data) => Ok(ByteStr(data.clone())),
+        LitKind::ByteStr(ref data) => Ok(ByteStr(ByteArray { data })),
         LitKind::Byte(n) => Ok(Integral(U8(n))),
         LitKind::Int(n, hint) => {
             match (&ty.sty, hint) {
@@ -708,8 +718,8 @@ pub fn compare_const_vals(tcx: TyCtxt, span: Span, a: &ConstVal, b: &ConstVal)
         (&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(ref a), &ByteStr(ref b)) => Some(a.cmp(b)),
-        (&Char(a), &Char(ref b)) => Some(a.cmp(b)),
+        (&ByteStr(a), &ByteStr(b)) => Some(a.data.cmp(b.data)),
+        (&Char(a), &Char(b)) => Some(a.cmp(&b)),
         _ => None,
     };
 
@@ -729,8 +739,8 @@ pub fn compare_const_vals(tcx: TyCtxt, span: Span, a: &ConstVal, b: &ConstVal)
 impl<'a, 'tcx> ConstContext<'a, 'tcx> {
     pub fn compare_lit_exprs(&self,
                              span: Span,
-                             a: &Expr,
-                             b: &Expr) -> Result<Ordering, ErrorReported> {
+                             a: &'tcx Expr,
+                             b: &'tcx Expr) -> Result<Ordering, ErrorReported> {
         let tcx = self.tcx;
         let a = match self.eval(a) {
             Ok(a) => a,
diff --git a/src/librustc_const_eval/pattern.rs b/src/librustc_const_eval/pattern.rs
index 692778f94e7..e824c4789c7 100644
--- a/src/librustc_const_eval/pattern.rs
+++ b/src/librustc_const_eval/pattern.rs
@@ -83,12 +83,12 @@ pub enum PatternKind<'tcx> {
     },
 
     Constant {
-        value: ConstVal<'tcx>,
+        value: &'tcx ConstVal<'tcx>,
     },
 
     Range {
-        lo: ConstVal<'tcx>,
-        hi: ConstVal<'tcx>,
+        lo: &'tcx ConstVal<'tcx>,
+        hi: &'tcx ConstVal<'tcx>,
         end: RangeEnd,
     },
 
@@ -112,15 +112,12 @@ fn print_const_val(value: &ConstVal, f: &mut fmt::Formatter) -> fmt::Result {
         ConstVal::Float(ref x) => write!(f, "{}", x),
         ConstVal::Integral(ref i) => write!(f, "{}", i),
         ConstVal::Str(ref s) => write!(f, "{:?}", &s[..]),
-        ConstVal::ByteStr(ref b) => write!(f, "{:?}", &b[..]),
+        ConstVal::ByteStr(b) => write!(f, "{:?}", b.data),
         ConstVal::Bool(b) => write!(f, "{:?}", b),
         ConstVal::Char(c) => write!(f, "{:?}", c),
         ConstVal::Variant(_) |
-        ConstVal::Struct(_) |
-        ConstVal::Tuple(_) |
         ConstVal::Function(..) |
-        ConstVal::Array(..) |
-        ConstVal::Repeat(..) => bug!("{:?} not printable in a pattern", value)
+        ConstVal::Aggregate(_) => bug!("{:?} not printable in a pattern", value)
     }
 }
 
@@ -230,12 +227,12 @@ impl<'tcx> fmt::Display for Pattern<'tcx> {
                 }
                 write!(f, "{}", subpattern)
             }
-            PatternKind::Constant { ref value } => {
+            PatternKind::Constant { value } => {
                 print_const_val(value, f)
             }
-            PatternKind::Range { ref lo, ref hi, ref end } => {
+            PatternKind::Range { lo, hi, end } => {
                 print_const_val(lo, f)?;
-                match *end {
+                match end {
                     RangeEnd::Included => write!(f, "...")?,
                     RangeEnd::Excluded => write!(f, "..")?,
                 }
@@ -278,7 +275,7 @@ impl<'a, 'tcx> Pattern<'tcx> {
     pub fn from_hir(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     param_env_and_substs: ty::ParamEnvAnd<'tcx, &'tcx Substs<'tcx>>,
                     tables: &'a ty::TypeckTables<'tcx>,
-                    pat: &hir::Pat) -> Self {
+                    pat: &'tcx hir::Pat) -> Self {
         let mut pcx = PatternContext::new(tcx, param_env_and_substs, tables);
         let result = pcx.lower_pattern(pat);
         if !pcx.errors.is_empty() {
@@ -302,7 +299,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
         }
     }
 
-    pub fn lower_pattern(&mut self, pat: &hir::Pat) -> Pattern<'tcx> {
+    pub fn lower_pattern(&mut self, pat: &'tcx hir::Pat) -> Pattern<'tcx> {
         let mut ty = self.tables.node_id_to_type(pat.hir_id);
 
         let kind = match pat.node {
@@ -310,11 +307,11 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
 
             PatKind::Lit(ref value) => self.lower_lit(value),
 
-            PatKind::Range(ref lo, ref hi, ref end) => {
+            PatKind::Range(ref lo, ref hi, end) => {
                 match (self.lower_lit(lo), self.lower_lit(hi)) {
                     (PatternKind::Constant { value: lo },
                      PatternKind::Constant { value: hi }) => {
-                        PatternKind::Range { lo: lo, hi: hi, end: end.clone() }
+                        PatternKind::Range { lo, hi, end }
                     }
                     _ => PatternKind::Wild
                 }
@@ -474,11 +471,11 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
         }
     }
 
-    fn lower_patterns(&mut self, pats: &[P<hir::Pat>]) -> Vec<Pattern<'tcx>> {
+    fn lower_patterns(&mut self, pats: &'tcx [P<hir::Pat>]) -> Vec<Pattern<'tcx>> {
         pats.iter().map(|p| self.lower_pattern(p)).collect()
     }
 
-    fn lower_opt_pattern(&mut self, pat: &Option<P<hir::Pat>>) -> Option<Pattern<'tcx>>
+    fn lower_opt_pattern(&mut self, pat: &'tcx Option<P<hir::Pat>>) -> Option<Pattern<'tcx>>
     {
         pat.as_ref().map(|p| self.lower_pattern(p))
     }
@@ -521,9 +518,9 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
         &mut self,
         span: Span,
         ty: Ty<'tcx>,
-        prefix: &[P<hir::Pat>],
-        slice: &Option<P<hir::Pat>>,
-        suffix: &[P<hir::Pat>])
+        prefix: &'tcx [P<hir::Pat>],
+        slice: &'tcx Option<P<hir::Pat>>,
+        suffix: &'tcx [P<hir::Pat>])
         -> PatternKind<'tcx>
     {
         let prefix = self.lower_patterns(prefix);
@@ -631,17 +628,17 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
         }
     }
 
-    fn lower_lit(&mut self, expr: &hir::Expr) -> PatternKind<'tcx> {
+    fn lower_lit(&mut self, expr: &'tcx hir::Expr) -> PatternKind<'tcx> {
         let const_cx = eval::ConstContext::new(self.tcx,
                                                self.param_env.and(self.substs),
                                                self.tables);
         match const_cx.eval(expr) {
             Ok(value) => {
-                if let ConstVal::Variant(def_id) = value {
+                if let ConstVal::Variant(def_id) = *value {
                     let ty = self.tables.expr_ty(expr);
                     self.lower_variant_or_leaf(Def::Variant(def_id), ty, vec![])
                 } else {
-                    PatternKind::Constant { value: value }
+                    PatternKind::Constant { value }
                 }
             }
             Err(e) => {
@@ -652,7 +649,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
     }
 
     fn lower_const_expr(&mut self,
-                        expr: &hir::Expr,
+                        expr: &'tcx hir::Expr,
                         pat_id: ast::NodeId,
                         span: Span)
                         -> Pattern<'tcx> {
@@ -819,8 +816,8 @@ macro_rules! CloneImpls {
 }
 
 CloneImpls!{ <'tcx>
-    Span, Field, Mutability, ast::Name, ast::NodeId, usize, ConstVal<'tcx>, Region<'tcx>,
-    Ty<'tcx>, BindingMode<'tcx>, &'tcx AdtDef,
+    Span, Field, Mutability, ast::Name, ast::NodeId, usize, &'tcx ConstVal<'tcx>,
+    Region<'tcx>, Ty<'tcx>, BindingMode<'tcx>, &'tcx AdtDef,
     &'tcx Substs<'tcx>, &'tcx Kind<'tcx>
 }
 
@@ -892,18 +889,18 @@ impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> {
                 subpattern: subpattern.fold_with(folder),
             },
             PatternKind::Constant {
-                ref value
+                value
             } => PatternKind::Constant {
                 value: value.fold_with(folder)
             },
             PatternKind::Range {
-                ref lo,
-                ref hi,
-                ref end,
+                lo,
+                hi,
+                end,
             } => PatternKind::Range {
                 lo: lo.fold_with(folder),
                 hi: hi.fold_with(folder),
-                end: end.clone(),
+                end,
             },
             PatternKind::Slice {
                 ref prefix,
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index ccd3194b5e3..46a33ce807d 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -76,7 +76,7 @@ impl LintPass for TypeLimits {
 }
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
-    fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
+    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx hir::Expr) {
         match e.node {
             hir::ExprUnary(hir::UnNeg, ref expr) => {
                 // propagate negation, if the negation itself isn't negated
@@ -117,7 +117,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
                                                              cx.param_env.and(substs),
                                                              cx.tables);
                             match const_cx.eval(&r) {
-                                Ok(ConstVal::Integral(i)) => {
+                                Ok(&ConstVal::Integral(i)) => {
                                     i.is_negative() ||
                                     i.to_u64()
                                         .map(|i| i >= bits)
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 73f1ae253cd..b475b02ccfe 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -16,6 +16,7 @@ use schema::*;
 use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash};
 use rustc::hir;
 
+use rustc::middle::const_val::{ByteArray, ConstVal};
 use rustc::middle::cstore::LinkagePreference;
 use rustc::hir::def::{self, Def, CtorKind};
 use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
@@ -377,6 +378,20 @@ impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Slice<ty::ExistentialPredicate<'tcx>
     }
 }
 
+impl<'a, 'tcx> SpecializedDecoder<ByteArray<'tcx>> for DecodeContext<'a, 'tcx> {
+    fn specialized_decode(&mut self) -> Result<ByteArray<'tcx>, Self::Error> {
+        Ok(ByteArray {
+            data: self.tcx().alloc_byte_array(&Vec::decode(self)?)
+        })
+    }
+}
+
+impl<'a, 'tcx> SpecializedDecoder<&'tcx ConstVal<'tcx>> for DecodeContext<'a, 'tcx> {
+    fn specialized_decode(&mut self) -> Result<&'tcx ConstVal<'tcx>, Self::Error> {
+        Ok(self.tcx().mk_const(Decodable::decode(self)?))
+    }
+}
+
 impl<'a, 'tcx> MetadataBlob {
     pub fn is_compatible(&self) -> bool {
         self.raw_bytes().starts_with(METADATA_HEADER)
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs
index c83283ee38e..c5f83b029ce 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir/build/expr/as_rvalue.rs
@@ -197,7 +197,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                         span: expr_span,
                         ty: this.hir.tcx().types.u32,
                         literal: Literal::Value {
-                            value: ConstVal::Integral(ConstInt::U32(0)),
+                            value: this.hir.tcx().mk_const(ConstVal::Integral(ConstInt::U32(0))),
                         },
                     }));
                     box AggregateKind::Generator(closure_id, substs, interior)
@@ -391,7 +391,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     }
                 };
 
-                Literal::Value { value: ConstVal::Integral(val) }
+                Literal::Value {
+                    value: self.hir.tcx().mk_const(ConstVal::Integral(val))
+                }
             }
             _ => {
                 span_bug!(span, "Invalid type for neg_1_literal: `{:?}`", ty)
@@ -424,7 +426,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     }
                 };
 
-                Literal::Value { value: ConstVal::Integral(val) }
+                Literal::Value {
+                    value: self.hir.tcx().mk_const(ConstVal::Integral(val))
+                }
             }
             _ => {
                 span_bug!(span, "Invalid type for minval_literal: `{:?}`", ty)
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs
index ec2e487b4e7..2d029f1a5b7 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir/build/matches/mod.rs
@@ -301,13 +301,13 @@ enum TestKind<'tcx> {
     // test the branches of enum
     SwitchInt {
         switch_ty: Ty<'tcx>,
-        options: Vec<ConstVal<'tcx>>,
-        indices: FxHashMap<ConstVal<'tcx>, usize>,
+        options: Vec<&'tcx ConstVal<'tcx>>,
+        indices: FxHashMap<&'tcx ConstVal<'tcx>, usize>,
     },
 
     // test for equality
     Eq {
-        value: ConstVal<'tcx>,
+        value: &'tcx ConstVal<'tcx>,
         ty: Ty<'tcx>,
     },
 
diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs
index 0b91e08fc6d..5553e2f4c9c 100644
--- a/src/librustc_mir/build/matches/test.rs
+++ b/src/librustc_mir/build/matches/test.rs
@@ -61,24 +61,24 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 }
             }
 
-            PatternKind::Constant { ref value } => {
+            PatternKind::Constant { value } => {
                 Test {
                     span: match_pair.pattern.span,
                     kind: TestKind::Eq {
-                        value: value.clone(),
+                        value,
                         ty: match_pair.pattern.ty.clone()
                     }
                 }
             }
 
-            PatternKind::Range { ref lo, ref hi, ref end } => {
+            PatternKind::Range { lo, hi, end } => {
                 Test {
                     span: match_pair.pattern.span,
                     kind: TestKind::Range {
-                        lo: Literal::Value { value: lo.clone() },
-                        hi: Literal::Value { value: hi.clone() },
+                        lo: Literal::Value { value: lo },
+                        hi: Literal::Value { value: hi },
                         ty: match_pair.pattern.ty.clone(),
-                        end: end.clone(),
+                        end,
                     },
                 }
             }
@@ -112,8 +112,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                                      test_lvalue: &Lvalue<'tcx>,
                                      candidate: &Candidate<'pat, 'tcx>,
                                      switch_ty: Ty<'tcx>,
-                                     options: &mut Vec<ConstVal<'tcx>>,
-                                     indices: &mut FxHashMap<ConstVal<'tcx>, usize>)
+                                     options: &mut Vec<&'tcx ConstVal<'tcx>>,
+                                     indices: &mut FxHashMap<&'tcx ConstVal<'tcx>, usize>)
                                      -> bool
     {
         let match_pair = match candidate.match_pairs.iter().find(|mp| mp.lvalue == *test_lvalue) {
@@ -122,13 +122,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         };
 
         match *match_pair.pattern.kind {
-            PatternKind::Constant { ref value } => {
+            PatternKind::Constant { value } => {
                 // if the lvalues match, the type should match
                 assert_eq!(match_pair.pattern.ty, switch_ty);
 
-                indices.entry(value.clone())
+                indices.entry(value)
                        .or_insert_with(|| {
-                           options.push(value.clone());
+                           options.push(value);
                            options.len() - 1
                        });
                 true
@@ -228,9 +228,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     assert!(options.len() > 0 && options.len() <= 2);
                     let (true_bb, false_bb) = (self.cfg.start_new_block(),
                                                self.cfg.start_new_block());
-                    let ret = match &options[0] {
-                        &ConstVal::Bool(true) => vec![true_bb, false_bb],
-                        &ConstVal::Bool(false) => vec![false_bb, true_bb],
+                    let ret = match *options[0] {
+                        ConstVal::Bool(true) => vec![true_bb, false_bb],
+                        ConstVal::Bool(false) => vec![false_bb, true_bb],
                         v => span_bug!(test.span, "expected boolean value but got {:?}", v)
                     };
                     (ret, TerminatorKind::if_(self.hir.tcx(), Operand::Consume(lvalue.clone()),
@@ -258,12 +258,12 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 ret
             }
 
-            TestKind::Eq { ref value, mut ty } => {
+            TestKind::Eq { value, mut ty } => {
                 let mut val = Operand::Consume(lvalue.clone());
 
                 // If we're using b"..." as a pattern, we need to insert an
                 // unsizing coercion, as the byte string has the type &[u8; N].
-                let expect = if let ConstVal::ByteStr(ref bytes) = *value {
+                let expect = if let ConstVal::ByteStr(bytes) = *value {
                     let tcx = self.hir.tcx();
 
                     // Unsize the lvalue to &[u8], too, if necessary.
@@ -279,10 +279,10 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
 
                     assert!(ty.is_slice());
 
-                    let array_ty = tcx.mk_array(tcx.types.u8, bytes.len());
+                    let array_ty = tcx.mk_array(tcx.types.u8, bytes.data.len());
                     let array_ref = tcx.mk_imm_ref(tcx.types.re_static, array_ty);
                     let array = self.literal_operand(test.span, array_ref, Literal::Value {
-                        value: value.clone()
+                        value
                     });
 
                     let slice = self.temp(ty, test.span);
@@ -291,7 +291,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     Operand::Consume(slice)
                 } else {
                     self.literal_operand(test.span, ty, Literal::Value {
-                        value: value.clone()
+                        value
                     })
                 };
 
diff --git a/src/librustc_mir/build/misc.rs b/src/librustc_mir/build/misc.rs
index 0e4aac42991..12b9174f3a3 100644
--- a/src/librustc_mir/build/misc.rs
+++ b/src/librustc_mir/build/misc.rs
@@ -59,7 +59,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             ty::TyBool => {
                 self.hir.false_literal()
             }
-            ty::TyChar => Literal::Value { value: ConstVal::Char('\0') },
+            ty::TyChar => {
+                Literal::Value {
+                    value: self.hir.tcx().mk_const(ConstVal::Char('\0'))
+                }
+            }
             ty::TyUint(ity) => {
                 let val = match ity {
                     ast::UintTy::U8  => ConstInt::U8(0),
@@ -74,7 +78,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     }
                 };
 
-                Literal::Value { value: ConstVal::Integral(val) }
+                Literal::Value {
+                    value: self.hir.tcx().mk_const(ConstVal::Integral(val))
+                }
             }
             ty::TyInt(ity) => {
                 let val = match ity {
@@ -90,7 +96,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     }
                 };
 
-                Literal::Value { value: ConstVal::Integral(val) }
+                Literal::Value {
+                    value: self.hir.tcx().mk_const(ConstVal::Integral(val))
+                }
             }
             _ => {
                 span_bug!(span, "Invalid type for zero_literal: `{:?}`", ty)
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index a245411002f..704d138b43b 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -11,7 +11,6 @@
 
 use build;
 use hair::cx::Cx;
-use hair::Pattern;
 use rustc::hir;
 use rustc::hir::def_id::DefId;
 use rustc::middle::region;
@@ -537,10 +536,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             let lvalue = Lvalue::Local(Local::new(index + 1));
 
             if let Some(pattern) = pattern {
-                let pattern = Pattern::from_hir(self.hir.tcx().global_tcx(),
-                                                self.hir.param_env.and(self.hir.identity_substs),
-                                                self.hir.tables(),
-                                                pattern);
+                let pattern = self.hir.pattern_from_hir(pattern);
                 scope = self.declare_bindings(scope, ast_body.span, &pattern);
                 unpack!(block = self.lvalue_into_pattern(block, pattern, &lvalue));
             }
diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs
index 8b3031a3800..f6b847d6d6d 100644
--- a/src/librustc_mir/hair/cx/block.rs
+++ b/src/librustc_mir/hair/cx/block.rs
@@ -64,10 +64,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                             first_statement_index: index as u32,
                         });
 
-                        let pattern = Pattern::from_hir(cx.tcx.global_tcx(),
-                                                        cx.param_env.and(cx.identity_substs),
-                                                        cx.tables(),
-                                                        &local.pat);
+                        let pattern = cx.pattern_from_hir(&local.pat);
                         result.push(StmtRef::Mirror(Box::new(Stmt {
                             kind: StmtKind::Let {
                                 remainder_scope: remainder_scope,
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index 9de5262cd88..0e4d2b9a5ae 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -473,7 +473,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             let def_id = cx.tcx.hir.body_owner_def_id(count);
             let substs = Substs::identity_for_item(cx.tcx.global_tcx(), def_id);
             let count = match cx.tcx.at(c.span).const_eval(cx.param_env.and((def_id, substs))) {
-                Ok(ConstVal::Integral(ConstInt::Usize(u))) => u,
+                Ok(&ConstVal::Integral(ConstInt::Usize(u))) => u,
                 Ok(other) => bug!("constant evaluation of repeat count yielded {:?}", other),
                 Err(s) => cx.fatal_const_eval_err(&s, c.span, "expression")
             };
@@ -597,7 +597,7 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         span: expr.span,
         kind: ExprKind::Literal {
             literal: Literal::Value {
-                value: ConstVal::Function(def_id, substs),
+                value: cx.tcx.mk_const(ConstVal::Function(def_id, substs)),
             },
         },
     }
@@ -612,12 +612,7 @@ fn to_borrow_kind(m: hir::Mutability) -> BorrowKind {
 
 fn convert_arm<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, arm: &'tcx hir::Arm) -> Arm<'tcx> {
     Arm {
-        patterns: arm.pats.iter().map(|p| {
-            Pattern::from_hir(cx.tcx.global_tcx(),
-                              cx.param_env.and(cx.identity_substs),
-                              cx.tables(),
-                              p)
-        }).collect(),
+        patterns: arm.pats.iter().map(|p| cx.pattern_from_hir(p)).collect(),
         guard: arm.guard.to_ref(),
         body: arm.body.to_ref(),
     }
@@ -635,7 +630,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         Def::StructCtor(def_id, CtorKind::Fn) |
         Def::VariantCtor(def_id, CtorKind::Fn) => ExprKind::Literal {
             literal: Literal::Value {
-                value: ConstVal::Function(def_id, substs),
+                value: cx.tcx.mk_const(ConstVal::Function(def_id, substs)),
             },
         },
 
diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs
index 3cabd8f18c1..9244ea14514 100644
--- a/src/librustc_mir/hair/cx/mod.rs
+++ b/src/librustc_mir/hair/cx/mod.rs
@@ -113,7 +113,11 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
 
     pub fn usize_literal(&mut self, value: u64) -> Literal<'tcx> {
         match ConstUsize::new(value, self.tcx.sess.target.uint_type) {
-            Ok(val) => Literal::Value { value: ConstVal::Integral(ConstInt::Usize(val)) },
+            Ok(val) => {
+                Literal::Value {
+                    value: self.tcx.mk_const(ConstVal::Integral(ConstInt::Usize(val)))
+                }
+            }
             Err(_) => bug!("usize literal out of range for target"),
         }
     }
@@ -127,11 +131,11 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
     }
 
     pub fn true_literal(&mut self) -> Literal<'tcx> {
-        Literal::Value { value: ConstVal::Bool(true) }
+        Literal::Value { value: self.tcx.mk_const(ConstVal::Bool(true)) }
     }
 
     pub fn false_literal(&mut self) -> Literal<'tcx> {
-        Literal::Value { value: ConstVal::Bool(false) }
+        Literal::Value { value: self.tcx.mk_const(ConstVal::Bool(false)) }
     }
 
     pub fn const_eval_literal(&mut self, e: &hir::Expr) -> Literal<'tcx> {
@@ -139,12 +143,24 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
         let const_cx = ConstContext::new(tcx,
                                          self.param_env.and(self.identity_substs),
                                          self.tables());
-        match const_cx.eval(e) {
-            Ok(value) => Literal::Value { value: value },
+        match const_cx.eval(tcx.hir.expect_expr(e.id)) {
+            Ok(value) => Literal::Value { value },
             Err(s) => self.fatal_const_eval_err(&s, e.span, "expression")
         }
     }
 
+    pub fn pattern_from_hir(&mut self, p: &hir::Pat) -> Pattern<'tcx> {
+        let tcx = self.tcx.global_tcx();
+        let p = match tcx.hir.get(p.id) {
+            hir::map::NodePat(p) | hir::map::NodeBinding(p) => p,
+            node => bug!("pattern became {:?}", node)
+        };
+        Pattern::from_hir(tcx,
+                          self.param_env.and(self.identity_substs),
+                          self.tables(),
+                          p)
+    }
+
     pub fn fatal_const_eval_err(&mut self,
         err: &ConstEvalErr<'tcx>,
         primary_span: Span,
@@ -170,7 +186,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
                 let method_ty = method_ty.subst(self.tcx, substs);
                 return (method_ty,
                         Literal::Value {
-                            value: ConstVal::Function(item.def_id, substs),
+                            value: self.tcx.mk_const(ConstVal::Function(item.def_id, substs)),
                         });
             }
         }
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index ec545443bcd..d0a78b57217 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -407,7 +407,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
             span: self.span,
             ty: tcx.mk_fn_def(self.def_id, substs),
             literal: Literal::Value {
-                value: ConstVal::Function(self.def_id, substs),
+                value: tcx.mk_const(ConstVal::Function(self.def_id, substs)),
             },
         });
 
@@ -472,7 +472,7 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
             span: self.span,
             ty: self.tcx.types.usize,
             literal: Literal::Value {
-                value: ConstVal::Integral(ConstInt::Usize(value))
+                value: self.tcx.mk_const(ConstVal::Integral(ConstInt::Usize(value)))
             }
         }
     }
@@ -711,8 +711,8 @@ fn build_call_shim<'a, 'tcx>(tcx: ty::TyCtxt<'a, 'tcx, 'tcx>,
                 span,
                 ty: tcx.type_of(def_id),
                 literal: Literal::Value {
-                    value: ConstVal::Function(def_id,
-                        Substs::identity_for_item(tcx, def_id)),
+                    value: tcx.mk_const(ConstVal::Function(def_id,
+                        Substs::identity_for_item(tcx, def_id))),
                 },
             }),
             vec![rcvr]
diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs
index d6477f2babf..971df70a74e 100644
--- a/src/librustc_mir/transform/elaborate_drops.rs
+++ b/src/librustc_mir/transform/elaborate_drops.rs
@@ -520,7 +520,9 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
         Rvalue::Use(Operand::Constant(Box::new(Constant {
             span,
             ty: self.tcx.types.bool,
-            literal: Literal::Value { value: ConstVal::Bool(val) }
+            literal: Literal::Value {
+                value: self.tcx.mk_const(ConstVal::Bool(val))
+            }
         })))
     }
 
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index 0fb34c96b06..74edf510aa2 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -175,7 +175,7 @@ impl<'a, 'tcx> TransformVisitor<'a, 'tcx> {
             span: source_info.span,
             ty: self.tcx.types.u32,
             literal: Literal::Value {
-                value: ConstVal::Integral(ConstInt::U32(state_disc)),
+                value: self.tcx.mk_const(ConstVal::Integral(ConstInt::U32(state_disc))),
             },
         });
         Statement {
@@ -553,7 +553,7 @@ fn insert_panic_on_resume_after_return<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             span: mir.span,
             ty: tcx.types.bool,
             literal: Literal::Value {
-                value: ConstVal::Bool(false),
+                value: tcx.mk_const(ConstVal::Bool(false)),
             },
         }),
         expected: true,
@@ -603,7 +603,7 @@ fn create_generator_resume_function<'a, 'tcx>(
             span: mir.span,
             ty: tcx.types.bool,
             literal: Literal::Value {
-                value: ConstVal::Bool(false),
+                value: tcx.mk_const(ConstVal::Bool(false)),
             },
         }),
         expected: true,
diff --git a/src/librustc_mir/transform/simplify_branches.rs b/src/librustc_mir/transform/simplify_branches.rs
index 1dcacb29c3e..6c0a44b7631 100644
--- a/src/librustc_mir/transform/simplify_branches.rs
+++ b/src/librustc_mir/transform/simplify_branches.rs
@@ -56,7 +56,7 @@ impl MirPass for SimplifyBranches {
                 },
                 TerminatorKind::Assert { target, cond: Operand::Constant(box Constant {
                     literal: Literal::Value {
-                        value: ConstVal::Bool(cond)
+                        value: &ConstVal::Bool(cond)
                     }, ..
                 }), expected, .. } if cond == expected => {
                     TerminatorKind::Goto { target: target }
diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs
index 7fbeb9610f4..eaafdb0ac41 100644
--- a/src/librustc_mir/transform/type_check.rs
+++ b/src/librustc_mir/transform/type_check.rs
@@ -572,7 +572,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         match operand {
             &Operand::Constant(box Constant {
                 literal: Literal::Value {
-                    value: ConstVal::Function(def_id, _), ..
+                    value: &ConstVal::Function(def_id, _), ..
                 }, ..
             }) => {
                 Some(def_id) == self.tcx().lang_items().box_free_fn()
diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs
index 8ea47c29910..d770dbe6f4f 100644
--- a/src/librustc_mir/util/elaborate_drops.rs
+++ b/src/librustc_mir/util/elaborate_drops.rs
@@ -922,7 +922,9 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
         Operand::Constant(box Constant {
             span: self.source_info.span,
             ty: self.tcx().types.usize,
-            literal: Literal::Value { value: ConstVal::Integral(self.tcx().const_usize(val)) }
+            literal: Literal::Value {
+                value: self.tcx().mk_const(ConstVal::Integral(self.tcx().const_usize(val)))
+            }
         })
     }
 
diff --git a/src/librustc_passes/mir_stats.rs b/src/librustc_passes/mir_stats.rs
index 3273d66dd4f..67176276f96 100644
--- a/src/librustc_passes/mir_stats.rs
+++ b/src/librustc_passes/mir_stats.rs
@@ -257,7 +257,7 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> {
     }
 
     fn visit_const_val(&mut self,
-                       const_val: &ConstVal,
+                       const_val: &&'tcx ConstVal<'tcx>,
                        _: Location) {
         self.record("ConstVal", const_val);
         self.super_const_val(const_val);
diff --git a/src/librustc_trans/mir/analyze.rs b/src/librustc_trans/mir/analyze.rs
index 949b9fe71ca..a843b4171bd 100644
--- a/src/librustc_trans/mir/analyze.rs
+++ b/src/librustc_trans/mir/analyze.rs
@@ -110,7 +110,7 @@ impl<'mir, 'a, 'tcx> Visitor<'tcx> for LocalAnalyzer<'mir, 'a, 'tcx> {
             mir::TerminatorKind::Call {
                 func: mir::Operand::Constant(box mir::Constant {
                     literal: Literal::Value {
-                        value: ConstVal::Function(def_id, _), ..
+                        value: &ConstVal::Function(def_id, _), ..
                     }, ..
                 }),
                 ref args, ..
diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs
index 1109f34a148..d43911df83a 100644
--- a/src/librustc_trans/mir/constant.rs
+++ b/src/librustc_trans/mir/constant.rs
@@ -90,11 +90,11 @@ impl<'tcx> Const<'tcx> {
 
     /// Translate ConstVal into a LLVM constant value.
     pub fn from_constval<'a>(ccx: &CrateContext<'a, 'tcx>,
-                             cv: ConstVal,
+                             cv: &ConstVal,
                              ty: Ty<'tcx>)
                              -> Const<'tcx> {
         let llty = type_of::type_of(ccx, ty);
-        let val = match cv {
+        let val = match *cv {
             ConstVal::Float(v) => {
                 let bits = match v.ty {
                     ast::FloatTy::F32 => C_u32(ccx, v.bits as u32),
@@ -105,12 +105,11 @@ impl<'tcx> Const<'tcx> {
             ConstVal::Bool(v) => C_bool(ccx, v),
             ConstVal::Integral(ref i) => return Const::from_constint(ccx, i),
             ConstVal::Str(ref v) => C_str_slice(ccx, v.clone()),
-            ConstVal::ByteStr(ref v) => consts::addr_of(ccx, C_bytes(ccx, v), 1, "byte_str"),
+            ConstVal::ByteStr(v) => consts::addr_of(ccx, C_bytes(ccx, v.data), 1, "byte_str"),
             ConstVal::Char(c) => C_integral(Type::char(ccx), c as u64, false),
             ConstVal::Function(..) => C_null(type_of::type_of(ccx, ty)),
             ConstVal::Variant(_) |
-            ConstVal::Struct(_) | ConstVal::Tuple(_) |
-            ConstVal::Array(..) | ConstVal::Repeat(..) => {
+            ConstVal::Aggregate(..) => {
                 bug!("MIR must not use `{:?}` (aggregates are expanded to MIR rvalues)", cv)
             }
         };
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index e4ca0f82ea1..8c3cf481e5e 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -572,7 +572,7 @@ fn convert_enum_variant_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             }
 
             match result {
-                Ok(ConstVal::Integral(x)) => Some(x),
+                Ok(&ConstVal::Integral(x)) => Some(x),
                 _ => None
             }
         } else if let Some(discr) = repr_type.disr_incr(tcx, prev_discr) {