about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/mir/interpret/value.rs8
-rw-r--r--src/librustc/mir/mod.rs19
-rw-r--r--src/librustc/mir/visit.rs4
-rw-r--r--src/librustc/traits/project.rs11
-rw-r--r--src/librustc/traits/query/normalize.rs11
-rw-r--r--src/librustc/ty/codec.rs12
-rw-r--r--src/librustc/ty/context.rs43
-rw-r--r--src/librustc/ty/error.rs9
-rw-r--r--src/librustc/ty/flags.rs38
-rw-r--r--src/librustc/ty/fold.rs16
-rw-r--r--src/librustc/ty/inhabitedness/mod.rs19
-rw-r--r--src/librustc/ty/mod.rs2
-rw-r--r--src/librustc/ty/print/pretty.rs35
-rw-r--r--src/librustc/ty/relate.rs10
-rw-r--r--src/librustc/ty/structural_impls.rs86
-rw-r--r--src/librustc/ty/sty.rs79
-rw-r--r--src/librustc/ty/subst.rs29
-rw-r--r--src/librustc/ty/util.rs4
-rw-r--r--src/librustc/ty/walk.rs4
-rw-r--r--src/librustc/ty/wf.rs5
-rw-r--r--src/librustc_codegen_ssa/mir/constant.rs31
-rw-r--r--src/librustc_codegen_ssa/mir/operand.rs1
-rw-r--r--src/librustc_mir/borrow_check/error_reporting.rs4
-rw-r--r--src/librustc_mir/borrow_check/mutability_errors.rs4
-rw-r--r--src/librustc_mir/borrow_check/nll/renumber.rs2
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs67
-rw-r--r--src/librustc_mir/build/expr/as_rvalue.rs4
-rw-r--r--src/librustc_mir/build/matches/test.rs2
-rw-r--r--src/librustc_mir/build/misc.rs2
-rw-r--r--src/librustc_mir/build/mod.rs2
-rw-r--r--src/librustc_mir/const_eval.rs4
-rw-r--r--src/librustc_mir/hair/cx/expr.rs40
-rw-r--r--src/librustc_mir/hair/cx/mod.rs12
-rw-r--r--src/librustc_mir/hair/mod.rs4
-rw-r--r--src/librustc_mir/hair/pattern/_match.rs2
-rw-r--r--src/librustc_mir/hair/pattern/mod.rs16
-rw-r--r--src/librustc_mir/interpret/operand.rs37
-rw-r--r--src/librustc_mir/monomorphize/collector.rs79
-rw-r--r--src/librustc_mir/monomorphize/item.rs24
-rw-r--r--src/librustc_mir/shim.rs12
-rw-r--r--src/librustc_mir/transform/const_prop.rs2
-rw-r--r--src/librustc_mir/transform/elaborate_drops.rs4
-rw-r--r--src/librustc_mir/transform/erase_regions.rs2
-rw-r--r--src/librustc_mir/transform/generator.rs8
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs7
-rw-r--r--src/librustc_mir/transform/simplify_branches.rs4
-rw-r--r--src/librustc_mir/util/elaborate_drops.rs4
-rw-r--r--src/librustc_mir/util/pretty.rs19
-rw-r--r--src/librustc_traits/chalk_context/mod.rs11
-rw-r--r--src/librustc_traits/chalk_context/program_clauses.rs2
-rw-r--r--src/librustc_typeck/astconv.rs20
-rw-r--r--src/librustc_typeck/check/mod.rs4
-rw-r--r--src/librustc_typeck/check/wfcheck.rs14
-rw-r--r--src/librustc_typeck/constrained_type_params.rs9
-rw-r--r--src/librustc_typeck/variance/constraints.rs10
-rw-r--r--src/librustdoc/clean/mod.rs16
56 files changed, 367 insertions, 562 deletions
diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs
index 9620ac95d86..7b47c02de1b 100644
--- a/src/librustc/mir/interpret/value.rs
+++ b/src/librustc/mir/interpret/value.rs
@@ -1,7 +1,8 @@
 use std::fmt;
 use rustc_macros::HashStable;
 
-use crate::ty::{Ty, InferConst, ParamConst, layout::{HasDataLayout, Size}};
+use crate::ty::{Ty, InferConst, ParamConst, layout::{HasDataLayout, Size}, subst::SubstsRef};
+use crate::hir::def_id::DefId;
 
 use super::{EvalResult, Pointer, PointerArithmetic, Allocation, AllocId, sign_extend, truncate};
 
@@ -42,6 +43,10 @@ pub enum ConstValue<'tcx> {
     /// An allocation together with a pointer into the allocation.
     /// Invariant: the pointer's `AllocId` resolves to the allocation.
     ByRef(Pointer, &'tcx Allocation),
+
+    /// Used in the HIR by using `Unevaluated` everywhere and later normalizing to one of the other
+    /// variants when the code is monomorphic enough for that.
+    Unevaluated(DefId, SubstsRef<'tcx>),
 }
 
 #[cfg(target_arch = "x86_64")]
@@ -54,6 +59,7 @@ impl<'tcx> ConstValue<'tcx> {
             ConstValue::Param(_) |
             ConstValue::Infer(_) |
             ConstValue::ByRef(..) |
+            ConstValue::Unevaluated(..) |
             ConstValue::Slice(..) => None,
             ConstValue::Scalar(val) => Some(val),
         }
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index 718b506d051..9f2027e7d05 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -2179,8 +2179,8 @@ impl<'tcx> Operand<'tcx> {
             span,
             ty,
             user_ty: None,
-            literal: tcx.mk_lazy_const(
-                ty::LazyConst::Evaluated(ty::Const::zero_sized(ty)),
+            literal: tcx.mk_const(
+                ty::Const::zero_sized(ty),
             ),
         })
     }
@@ -2497,7 +2497,7 @@ pub struct Constant<'tcx> {
     /// Needed for NLL to impose user-given type constraints.
     pub user_ty: Option<UserTypeAnnotationIndex>,
 
-    pub literal: &'tcx ty::LazyConst<'tcx>,
+    pub literal: &'tcx ty::Const<'tcx>,
 }
 
 /// A collection of projections into user types.
@@ -2696,18 +2696,9 @@ newtype_index! {
 impl<'tcx> Debug for Constant<'tcx> {
     fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
         write!(fmt, "const ")?;
-        fmt_lazy_const_val(fmt, self.literal)
+        fmt_const_val(fmt, *self.literal)
     }
 }
-
-/// Write a `ConstValue` in a way closer to the original source code than the `Debug` output.
-pub fn fmt_lazy_const_val(f: &mut impl Write, const_val: &ty::LazyConst<'_>) -> fmt::Result {
-    match *const_val {
-        ty::LazyConst::Unevaluated(..) => write!(f, "{:?}", const_val),
-        ty::LazyConst::Evaluated(c) => fmt_const_val(f, c),
-    }
-}
-
 /// Write a `ConstValue` in a way closer to the original source code than the `Debug` output.
 pub fn fmt_const_val(f: &mut impl Write, const_val: ty::Const<'_>) -> fmt::Result {
     use crate::ty::TyKind::*;
@@ -2760,7 +2751,7 @@ pub fn fmt_const_val(f: &mut impl Write, const_val: ty::Const<'_>) -> fmt::Resul
         }
     }
     // just raw dump everything else
-    write!(f, "{:?}:{}", value, ty)
+    write!(f, "{:?} : {}", value, ty)
 }
 
 fn def_path_str(def_id: DefId) -> String {
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index 28e816f1343..8bc0075c477 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -232,7 +232,7 @@ macro_rules! make_mir_visitor {
             }
 
             fn visit_const(&mut self,
-                           constant: & $($mutability)? &'tcx ty::LazyConst<'tcx>,
+                           constant: & $($mutability)? &'tcx ty::Const<'tcx>,
                            _: Location) {
                 self.super_const(constant);
             }
@@ -886,7 +886,7 @@ macro_rules! make_mir_visitor {
             fn super_region(&mut self, _region: & $($mutability)? ty::Region<'tcx>) {
             }
 
-            fn super_const(&mut self, _const: & $($mutability)? &'tcx ty::LazyConst<'tcx>) {
+            fn super_const(&mut self, _const: & $($mutability)? &'tcx ty::Const<'tcx>) {
             }
 
             fn super_substs(&mut self, _substs: & $($mutability)? SubstsRef<'tcx>) {
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index ab6acc66213..360e2323b64 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -15,7 +15,7 @@ use super::util;
 use crate::hir::def_id::DefId;
 use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime};
 use crate::infer::type_variable::TypeVariableOrigin;
-use crate::mir::interpret::{GlobalId};
+use crate::mir::interpret::{GlobalId, ConstValue};
 use rustc_data_structures::snapshot_map::{Snapshot, SnapshotMap};
 use rustc_macros::HashStable;
 use syntax::ast::Ident;
@@ -397,8 +397,8 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a,
         }
     }
 
-    fn fold_const(&mut self, constant: &'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> {
-        if let ty::LazyConst::Unevaluated(def_id, substs) = *constant {
+    fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
+        if let ConstValue::Unevaluated(def_id, substs) = constant.val {
             let tcx = self.selcx.tcx().global_tcx();
             if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) {
                 if substs.needs_infer() || substs.has_placeholders() {
@@ -411,8 +411,9 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a,
                         };
                         if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
                             let substs = tcx.lift_to_global(&substs).unwrap();
+                            let evaluated = tcx.mk_const(evaluated);
                             let evaluated = evaluated.subst(tcx, substs);
-                            return tcx.mk_lazy_const(ty::LazyConst::Evaluated(evaluated));
+                            return evaluated;
                         }
                     }
                 } else {
@@ -424,7 +425,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a,
                                 promoted: None
                             };
                             if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
-                                return tcx.mk_lazy_const(ty::LazyConst::Evaluated(evaluated));
+                                return tcx.mk_const(evaluated);
                             }
                         }
                     }
diff --git a/src/librustc/traits/query/normalize.rs b/src/librustc/traits/query/normalize.rs
index 8a30c18d6e5..9940249da8b 100644
--- a/src/librustc/traits/query/normalize.rs
+++ b/src/librustc/traits/query/normalize.rs
@@ -5,7 +5,7 @@
 use crate::infer::at::At;
 use crate::infer::canonical::OriginalQueryValues;
 use crate::infer::{InferCtxt, InferOk};
-use crate::mir::interpret::GlobalId;
+use crate::mir::interpret::{GlobalId, ConstValue};
 use crate::traits::project::Normalized;
 use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
 use crate::ty::fold::{TypeFoldable, TypeFolder};
@@ -188,8 +188,8 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx
         }
     }
 
-    fn fold_const(&mut self, constant: &'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> {
-        if let ty::LazyConst::Unevaluated(def_id, substs) = *constant {
+    fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
+        if let ConstValue::Unevaluated(def_id, substs) = constant.val {
             let tcx = self.infcx.tcx.global_tcx();
             if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) {
                 if substs.needs_infer() || substs.has_placeholders() {
@@ -202,8 +202,9 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx
                         };
                         if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
                             let substs = tcx.lift_to_global(&substs).unwrap();
+                            let evaluated = tcx.mk_const(evaluated);
                             let evaluated = evaluated.subst(tcx, substs);
-                            return tcx.mk_lazy_const(ty::LazyConst::Evaluated(evaluated));
+                            return evaluated;
                         }
                     }
                 } else {
@@ -215,7 +216,7 @@ impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for QueryNormalizer<'cx, 'gcx, 'tcx
                                 promoted: None,
                             };
                             if let Ok(evaluated) = tcx.const_eval(param_env.and(cid)) {
-                                return tcx.mk_lazy_const(ty::LazyConst::Evaluated(evaluated));
+                                return tcx.mk_const(evaluated);
                             }
                         }
                     }
diff --git a/src/librustc/ty/codec.rs b/src/librustc/ty/codec.rs
index 3ab744ebaeb..e7474345c00 100644
--- a/src/librustc/ty/codec.rs
+++ b/src/librustc/ty/codec.rs
@@ -247,12 +247,12 @@ pub fn decode_canonical_var_infos<'a, 'tcx, D>(decoder: &mut D)
 }
 
 #[inline]
-pub fn decode_lazy_const<'a, 'tcx, D>(decoder: &mut D)
-                                 -> Result<&'tcx ty::LazyConst<'tcx>, D::Error>
+pub fn decode_const<'a, 'tcx, D>(decoder: &mut D)
+                                 -> Result<&'tcx ty::Const<'tcx>, D::Error>
     where D: TyDecoder<'a, 'tcx>,
           'tcx: 'a,
 {
-    Ok(decoder.tcx().mk_lazy_const(Decodable::decode(decoder)?))
+    Ok(decoder.tcx().mk_const(Decodable::decode(decoder)?))
 }
 
 #[inline]
@@ -389,10 +389,10 @@ macro_rules! implement_ty_decoder {
                 }
             }
 
-            impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::ty::LazyConst<'tcx>>
+            impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::ty::Const<'tcx>>
             for $DecoderName<$($typaram),*> {
-                fn specialized_decode(&mut self) -> Result<&'tcx ty::LazyConst<'tcx>, Self::Error> {
-                    decode_lazy_const(self)
+                fn specialized_decode(&mut self) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
+                    decode_const(self)
                 }
             }
 
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 1942f98abff..6de0a39c91b 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -28,7 +28,7 @@ use crate::traits;
 use crate::traits::{Clause, Clauses, GoalKind, Goal, Goals};
 use crate::ty::{self, DefIdTree, Ty, TypeAndMut};
 use crate::ty::{TyS, TyKind, List};
-use crate::ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorSubsts, Region, Const, LazyConst};
+use crate::ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorSubsts, Region, Const};
 use crate::ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate, Predicate};
 use crate::ty::RegionKind;
 use crate::ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid, ConstVid};
@@ -126,7 +126,7 @@ pub struct CtxtInterners<'tcx> {
     goal: InternedSet<'tcx, GoalKind<'tcx>>,
     goal_list: InternedSet<'tcx, List<Goal<'tcx>>>,
     projs: InternedSet<'tcx, List<ProjectionKind<'tcx>>>,
-    lazy_const: InternedSet<'tcx, LazyConst<'tcx>>,
+    const_: InternedSet<'tcx, Const<'tcx>>,
 }
 
 impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
@@ -144,7 +144,7 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
             goal: Default::default(),
             goal_list: Default::default(),
             projs: Default::default(),
-            lazy_const: Default::default(),
+            const_: Default::default(),
         }
     }
 
@@ -874,14 +874,11 @@ impl CanonicalUserType<'gcx> {
                             _ => false,
                         },
 
-                        UnpackedKind::Const(ct) => match ct {
-                            ty::LazyConst::Evaluated(ty::Const {
-                                val: ConstValue::Infer(InferConst::Canonical(debruijn, b)),
-                                ..
-                            }) => {
+                        UnpackedKind::Const(ct) => match ct.val {
+                            ConstValue::Infer(InferConst::Canonical(debruijn, b)) => {
                                 // We only allow a `ty::INNERMOST` index in substitutions.
-                                assert_eq!(*debruijn, ty::INNERMOST);
-                                cvar == *b
+                                assert_eq!(debruijn, ty::INNERMOST);
+                                cvar == b
                             }
                             _ => false,
                         },
@@ -1788,7 +1785,7 @@ macro_rules! nop_list_lift {
 nop_lift!{Ty<'a> => Ty<'tcx>}
 nop_lift!{Region<'a> => Region<'tcx>}
 nop_lift!{Goal<'a> => Goal<'tcx>}
-nop_lift!{&'a LazyConst<'a> => &'tcx LazyConst<'tcx>}
+nop_lift!{&'a Const<'a> => &'tcx Const<'tcx>}
 
 nop_list_lift!{Goal<'a> => Goal<'tcx>}
 nop_list_lift!{Clause<'a> => Clause<'tcx>}
@@ -2274,12 +2271,6 @@ impl<'tcx: 'lcx, 'lcx> Borrow<GoalKind<'lcx>> for Interned<'tcx, GoalKind<'tcx>>
     }
 }
 
-impl<'tcx: 'lcx, 'lcx> Borrow<LazyConst<'lcx>> for Interned<'tcx, LazyConst<'tcx>> {
-    fn borrow<'a>(&'a self) -> &'a LazyConst<'lcx> {
-        &self.0
-    }
-}
-
 impl<'tcx: 'lcx, 'lcx> Borrow<[ExistentialPredicate<'lcx>]>
     for Interned<'tcx, List<ExistentialPredicate<'tcx>>> {
     fn borrow<'a>(&'a self) -> &'a [ExistentialPredicate<'lcx>] {
@@ -2387,7 +2378,7 @@ pub fn keep_local<'tcx, T: ty::TypeFoldable<'tcx>>(x: &T) -> bool {
 direct_interners!('tcx,
     region: mk_region(|r: &RegionKind| r.keep_in_local_tcx()) -> RegionKind,
     goal: mk_goal(|c: &GoalKind<'_>| keep_local(c)) -> GoalKind<'tcx>,
-    lazy_const: mk_lazy_const(|c: &LazyConst<'_>| keep_local(&c)) -> LazyConst<'tcx>
+    const_: mk_const(|c: &Const<'_>| keep_local(&c)) -> Const<'tcx>
 );
 
 macro_rules! slice_interners {
@@ -2575,8 +2566,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 
     #[inline]
     pub fn mk_array(self, ty: Ty<'tcx>, n: u64) -> Ty<'tcx> {
-        self.mk_ty(Array(ty, self.mk_lazy_const(
-            ty::LazyConst::Evaluated(ty::Const::from_usize(self.global_tcx(), n))
+        self.mk_ty(Array(ty, self.mk_const(
+            ty::Const::from_usize(self.global_tcx(), n)
         )))
     }
 
@@ -2670,11 +2661,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     }
 
     #[inline]
-    pub fn mk_const_var(self, v: ConstVid<'tcx>, ty: Ty<'tcx>) -> &'tcx LazyConst<'tcx> {
-        self.mk_lazy_const(LazyConst::Evaluated(ty::Const {
+    pub fn mk_const_var(self, v: ConstVid<'tcx>, ty: Ty<'tcx>) -> &'tcx Const<'tcx> {
+        self.mk_const(ty::Const {
             val: ConstValue::Infer(InferConst::Var(v)),
             ty,
-        }))
+        })
     }
 
     #[inline]
@@ -2705,11 +2696,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         index: u32,
         name: InternedString,
         ty: Ty<'tcx>
-    ) -> &'tcx LazyConst<'tcx> {
-        self.mk_lazy_const(LazyConst::Evaluated(ty::Const {
+    ) -> &'tcx Const<'tcx> {
+        self.mk_const(ty::Const {
             val: ConstValue::Param(ParamConst { index, name }),
             ty,
-        }))
+        })
     }
 
     #[inline]
diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs
index fa3c76a817a..74d0a29bcff 100644
--- a/src/librustc/ty/error.rs
+++ b/src/librustc/ty/error.rs
@@ -176,12 +176,9 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> {
 
             ty::Adt(def, _) => format!("{} `{}`", def.descr(), tcx.def_path_str(def.did)).into(),
             ty::Foreign(def_id) => format!("extern type `{}`", tcx.def_path_str(def_id)).into(),
-            ty::Array(_, n) => match n {
-                ty::LazyConst::Evaluated(n) => match n.assert_usize(tcx) {
-                    Some(n) => format!("array of {} elements", n).into(),
-                    None => "array".into(),
-                },
-                ty::LazyConst::Unevaluated(..) => "array".into(),
+            ty::Array(_, n) => match n.assert_usize(tcx) {
+                Some(n) => format!("array of {} elements", n).into(),
+                None => "array".into(),
             }
             ty::Slice(_) => "slice".into(),
             ty::RawPtr(_) => "*-ptr".into(),
diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs
index 64ceb9729ed..7aed2a4288c 100644
--- a/src/librustc/ty/flags.rs
+++ b/src/librustc/ty/flags.rs
@@ -24,6 +24,12 @@ impl FlagComputation {
         result
     }
 
+    pub fn for_const(c: &ty::Const<'_>) -> TypeFlags {
+        let mut result = FlagComputation::new();
+        result.add_const(c);
+        result.flags
+    }
+
     fn add_flags(&mut self, flags: TypeFlags) {
         self.flags = self.flags | (flags & TypeFlags::NOMINAL_FLAGS);
     }
@@ -173,10 +179,7 @@ impl FlagComputation {
 
             &ty::Array(tt, len) => {
                 self.add_ty(tt);
-                if let ty::LazyConst::Unevaluated(_, substs) = len {
-                    self.add_flags(TypeFlags::HAS_PROJECTION);
-                    self.add_substs(substs);
-                }
+                self.add_const(len);
             }
 
             &ty::Slice(tt) => {
@@ -233,19 +236,26 @@ impl FlagComputation {
         }
     }
 
-    fn add_const(&mut self, c: &ty::LazyConst<'_>) {
-        match c {
-            ty::LazyConst::Unevaluated(_, substs) => self.add_substs(substs),
-            // Only done to add the binder for the type. The type flags are
-            // included in `Const::type_flags`.
-            ty::LazyConst::Evaluated(ty::Const { ty, val }) => {
-                self.add_ty(ty);
-                if let ConstValue::Infer(InferConst::Canonical(debruijn, _)) = val {
-                    self.add_binder(*debruijn)
+    fn add_const(&mut self, c: &ty::Const<'_>) {
+        self.add_ty(c.ty);
+        match c.val {
+            ConstValue::Unevaluated(_, substs) => {
+                self.add_substs(substs);
+                self.add_flags(TypeFlags::HAS_NORMALIZABLE_PROJECTION | TypeFlags::HAS_PROJECTION);
+            },
+            ConstValue::Infer(infer) => {
+                self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES | TypeFlags::HAS_CT_INFER);
+                match infer {
+                    InferConst::Fresh(_) => {}
+                    InferConst::Canonical(debruijn, _) => self.add_binder(debruijn),
+                    InferConst::Var(_) => self.add_flags(TypeFlags::KEEP_IN_LOCAL_TCX),
                 }
             }
+            ConstValue::Param(_) => {
+                self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES | TypeFlags::HAS_PARAMS);
+            }
+            _ => {},
         }
-        self.add_flags(c.type_flags());
     }
 
     fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection<'_>) {
diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs
index 7f77d037bb6..321e55270c6 100644
--- a/src/librustc/ty/fold.rs
+++ b/src/librustc/ty/fold.rs
@@ -32,7 +32,7 @@
 //! looking for, and does not need to visit anything else.
 
 use crate::hir::def_id::DefId;
-use crate::ty::{self, Binder, Ty, TyCtxt, TypeFlags};
+use crate::ty::{self, Binder, Ty, TyCtxt, TypeFlags, flags::FlagComputation};
 
 use std::collections::BTreeMap;
 use std::fmt;
@@ -167,7 +167,7 @@ pub trait TypeFolder<'gcx: 'tcx, 'tcx> : Sized {
         r.super_fold_with(self)
     }
 
-    fn fold_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> {
+    fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
         c.super_fold_with(self)
     }
 }
@@ -185,7 +185,7 @@ pub trait TypeVisitor<'tcx> : Sized {
         r.super_visit_with(self)
     }
 
-    fn visit_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> bool {
+    fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
         c.super_visit_with(self)
     }
 }
@@ -842,14 +842,10 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
         flags.intersects(self.flags)
     }
 
-    fn visit_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> bool {
-        let flags = c.type_flags();
+    fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
+        let flags = FlagComputation::for_const(c);
         debug!("HasTypeFlagsVisitor: c={:?} c.flags={:?} self.flags={:?}", c, flags, self.flags);
-        if flags.intersects(self.flags) {
-            true
-        } else {
-            c.super_visit_with(self)
-        }
+        flags.intersects(self.flags) || c.super_visit_with(self)
     }
 }
 
diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs
index 33ec9c874f9..d732f3ff040 100644
--- a/src/librustc/ty/inhabitedness/mod.rs
+++ b/src/librustc/ty/inhabitedness/mod.rs
@@ -1,6 +1,6 @@
 use crate::ty::context::TyCtxt;
 use crate::ty::{AdtDef, VariantDef, FieldDef, Ty, TyS};
-use crate::ty::{self, DefId, SubstsRef};
+use crate::ty::{DefId, SubstsRef};
 use crate::ty::{AdtKind, Visibility};
 use crate::ty::TyKind::*;
 
@@ -212,17 +212,12 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
                 }))
             }
 
-            Array(ty, len) => {
-                match len {
-                    ty::LazyConst::Unevaluated(..) => DefIdForest::empty(),
-                    ty::LazyConst::Evaluated(len) => match len.assert_usize(tcx) {
-                        // If the array is definitely non-empty, it's uninhabited if
-                        // the type of its elements is uninhabited.
-                        Some(n) if n != 0 => ty.uninhabited_from(tcx),
-                        _ => DefIdForest::empty()
-                    },
-                }
-            }
+            Array(ty, len) => match len.assert_usize(tcx) {
+                // If the array is definitely non-empty, it's uninhabited if
+                // the type of its elements is uninhabited.
+                Some(n) if n != 0 => ty.uninhabited_from(tcx),
+                _ => DefIdForest::empty()
+            },
 
             // References to uninitialised memory is valid for any type, including
             // uninhabited types, in unsafe code, so we treat all references as
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 882e2dc62b1..298af1d00c9 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -59,7 +59,7 @@ pub use self::sty::{InferTy, ParamTy, ParamConst, InferConst, ProjectionTy, Exis
 pub use self::sty::{ClosureSubsts, GeneratorSubsts, UpvarSubsts, TypeAndMut};
 pub use self::sty::{TraitRef, TyKind, PolyTraitRef};
 pub use self::sty::{ExistentialTraitRef, PolyExistentialTraitRef};
-pub use self::sty::{ExistentialProjection, PolyExistentialProjection, Const, LazyConst};
+pub use self::sty::{ExistentialProjection, PolyExistentialProjection, Const};
 pub use self::sty::{BoundRegion, EarlyBoundRegion, FreeRegion, Region};
 pub use self::sty::RegionKind;
 pub use self::sty::{TyVid, IntVid, FloatVid, ConstVid, RegionVid};
diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs
index fa57e0b9674..7701a10d8ee 100644
--- a/src/librustc/ty/print/pretty.rs
+++ b/src/librustc/ty/print/pretty.rs
@@ -660,18 +660,12 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>:
             },
             ty::Array(ty, sz) => {
                 p!(write("["), print(ty), write("; "));
-                match sz {
-                    ty::LazyConst::Unevaluated(_def_id, _substs) => {
-                        p!(write("_"));
-                    }
-                    ty::LazyConst::Evaluated(c) => {
-                        match c.val {
-                            ConstValue::Infer(..) => p!(write("_")),
-                            ConstValue::Param(ParamConst { name, .. }) =>
-                                p!(write("{}", name)),
-                            _ => p!(write("{}", c.unwrap_usize(self.tcx()))),
-                        }
-                    }
+                match sz.val {
+                    ConstValue::Unevaluated(..) |
+                    ConstValue::Infer(..) => p!(write("_")),
+                    ConstValue::Param(ParamConst { name, .. }) =>
+                        p!(write("{}", name)),
+                    _ => p!(write("{}", sz.unwrap_usize(self.tcx()))),
                 }
                 p!(write("]"))
             }
@@ -1533,26 +1527,15 @@ define_print_and_forward_display! {
         p!(print_def_path(self.def_id, self.substs));
     }
 
-    ConstValue<'tcx> {
-        match self {
+    &'tcx ty::Const<'tcx> {
+        match self.val {
+            ConstValue::Unevaluated(..) |
             ConstValue::Infer(..) => p!(write("_")),
             ConstValue::Param(ParamConst { name, .. }) => p!(write("{}", name)),
             _ => p!(write("{:?}", self)),
         }
     }
 
-    ty::Const<'tcx> {
-        p!(write("{} : {}", self.val, self.ty))
-    }
-
-    &'tcx ty::LazyConst<'tcx> {
-        match self {
-            // FIXME(const_generics) this should print at least the type.
-            ty::LazyConst::Unevaluated(..) => p!(write("_ : _")),
-            ty::LazyConst::Evaluated(c) => p!(write("{}", c)),
-        }
-    }
-
     ty::ParamTy {
         p!(write("{}", self.name))
     }
diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs
index b245d903799..810bd10c8f4 100644
--- a/src/librustc/ty/relate.rs
+++ b/src/librustc/ty/relate.rs
@@ -8,7 +8,7 @@ use crate::hir::def_id::DefId;
 use crate::ty::subst::{Kind, UnpackedKind, SubstsRef};
 use crate::ty::{self, Ty, TyCtxt, TypeFoldable};
 use crate::ty::error::{ExpectedFound, TypeError};
-use crate::mir::interpret::GlobalId;
+use crate::mir::interpret::{GlobalId, ConstValue};
 use crate::util::common::ErrorReported;
 use syntax_pos::DUMMY_SP;
 use std::rc::Rc;
@@ -466,9 +466,9 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
         (&ty::Array(a_t, sz_a), &ty::Array(b_t, sz_b)) =>
         {
             let t = relation.relate(&a_t, &b_t)?;
-            let to_u64 = |x: ty::LazyConst<'tcx>| -> Result<u64, ErrorReported> {
-                match x {
-                    ty::LazyConst::Unevaluated(def_id, substs) => {
+            let to_u64 = |x: ty::Const<'tcx>| -> Result<u64, ErrorReported> {
+                match x.val {
+                    ConstValue::Unevaluated(def_id, substs) => {
                         // FIXME(eddyb) get the right param_env.
                         let param_env = ty::ParamEnv::empty();
                         if let Some(substs) = tcx.lift_to_global(&substs) {
@@ -494,7 +494,7 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
                             "array length could not be evaluated");
                         Err(ErrorReported)
                     }
-                    ty::LazyConst::Evaluated(c) => c.assert_usize(tcx).ok_or_else(|| {
+                    _ => x.assert_usize(tcx).ok_or_else(|| {
                         tcx.sess.delay_span_bug(DUMMY_SP,
                             "array length could not be evaluated");
                         ErrorReported
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index ecfb034e4f2..cbdda732692 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -6,7 +6,7 @@
 use crate::hir::def::Namespace;
 use crate::mir::ProjectionKind;
 use crate::mir::interpret::ConstValue;
-use crate::ty::{self, Lift, Ty, TyCtxt, ConstVid, InferConst};
+use crate::ty::{self, Lift, Ty, TyCtxt, ConstVid};
 use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 use crate::ty::print::{FmtPrinter, Printer};
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
@@ -794,34 +794,6 @@ BraceStructLiftImpl! {
     }
 }
 
-BraceStructLiftImpl! {
-    impl<'a, 'tcx> Lift<'tcx> for ty::Const<'a> {
-        type Lifted = ty::Const<'tcx>;
-        val, ty
-    }
-}
-
-impl<'a, 'tcx> Lift<'tcx> for ConstValue<'a> {
-    type Lifted = ConstValue<'tcx>;
-    fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
-        match *self {
-            ConstValue::Param(param) => Some(ConstValue::Param(param)),
-            ConstValue::Infer(infer) => {
-                Some(ConstValue::Infer(match infer {
-                    InferConst::Var(vid) => InferConst::Var(vid.lift_to_tcx(tcx)?),
-                    InferConst::Fresh(i) => InferConst::Fresh(i),
-                    InferConst::Canonical(debrujin, var) => InferConst::Canonical(debrujin, var),
-                }))
-            }
-            ConstValue::Scalar(x) => Some(ConstValue::Scalar(x)),
-            ConstValue::Slice(x, y) => Some(ConstValue::Slice(x, y)),
-            ConstValue::ByRef(ptr, alloc) => Some(ConstValue::ByRef(
-                ptr, alloc.lift_to_tcx(tcx)?,
-            )),
-        }
-    }
-}
-
 impl<'a, 'tcx> Lift<'tcx> for ConstVid<'a> {
     type Lifted = ConstVid<'tcx>;
     fn lift_to_tcx<'b, 'gcx>(&self, _: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
@@ -1362,15 +1334,14 @@ EnumTypeFoldableImpl! {
     }
 }
 
-impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::LazyConst<'tcx> {
+impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Const<'tcx> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
-        let new = match self {
-            ty::LazyConst::Evaluated(v) => ty::LazyConst::Evaluated(v.fold_with(folder)),
-            ty::LazyConst::Unevaluated(def_id, substs) => {
-                ty::LazyConst::Unevaluated(*def_id, substs.fold_with(folder))
-            }
-        };
-        folder.tcx().mk_lazy_const(new)
+        let ty = self.ty.fold_with(folder);
+        let val = self.val.fold_with(folder);
+        folder.tcx().mk_const(ty::Const {
+            ty,
+            val
+        })
     }
 
     fn fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
@@ -1378,10 +1349,7 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::LazyConst<'tcx> {
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
-        match *self {
-            ty::LazyConst::Evaluated(c) => c.visit_with(visitor),
-            ty::LazyConst::Unevaluated(_, substs) => substs.visit_with(visitor),
-        }
+        self.ty.visit_with(visitor) || self.val.visit_with(visitor)
     }
 
     fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
@@ -1389,27 +1357,29 @@ impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::LazyConst<'tcx> {
     }
 }
 
-impl<'tcx> TypeFoldable<'tcx> for ty::Const<'tcx> {
+impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
-        let ty = self.ty.fold_with(folder);
-        let val = self.val.fold_with(folder);
-        ty::Const {
-            ty,
-            val
+        match *self {
+            ConstValue::ByRef(ptr, alloc) => ConstValue::ByRef(ptr, alloc),
+            // FIXME(const_generics): implement TypeFoldable for InferConst
+            ConstValue::Infer(ic) => ConstValue::Infer(ic),
+            ConstValue::Param(p) => ConstValue::Param(p.fold_with(folder)),
+            ConstValue::Scalar(a) => ConstValue::Scalar(a),
+            ConstValue::Slice(a, b) => ConstValue::Slice(a, b),
+            ConstValue::Unevaluated(did, substs)
+                => ConstValue::Unevaluated(did, substs.fold_with(folder)),
         }
     }
 
     fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
-        self.ty.visit_with(visitor) || self.val.visit_with(visitor)
-    }
-}
-
-impl<'tcx> TypeFoldable<'tcx> for ConstValue<'tcx> {
-    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _folder: &mut F) -> Self {
-        *self
-    }
-
-    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> bool {
-        false
+        match *self {
+            ConstValue::ByRef(..) => false,
+            // FIXME(const_generics): implement TypeFoldable for InferConst
+            ConstValue::Infer(_ic) => false,
+            ConstValue::Param(p) => p.visit_with(visitor),
+            ConstValue::Scalar(_) => false,
+            ConstValue::Slice(..) => false,
+            ConstValue::Unevaluated(_, substs) => substs.visit_with(visitor),
+        }
     }
 }
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 7b6a51c0184..df76e6127e8 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -118,7 +118,7 @@ pub enum TyKind<'tcx> {
     Str,
 
     /// An array with the given length. Written as `[T; n]`.
-    Array(Ty<'tcx>, &'tcx ty::LazyConst<'tcx>),
+    Array(Ty<'tcx>, &'tcx ty::Const<'tcx>),
 
     /// The pointee of an array slice. Written as `[T]`.
     Slice(Ty<'tcx>),
@@ -1089,7 +1089,7 @@ impl<'a, 'gcx, 'tcx> ParamConst {
         ParamConst::new(def.index, def.name)
     }
 
-    pub fn to_const(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, ty: Ty<'tcx>) -> &'tcx LazyConst<'tcx> {
+    pub fn to_const(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, ty: Ty<'tcx>) -> &'tcx Const<'tcx> {
         tcx.mk_const_param(self.index, self.name, ty)
     }
 }
@@ -2096,52 +2096,6 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
     }
 }
 
-#[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable,
-         Eq, PartialEq, Ord, PartialOrd, HashStable)]
-/// Used in the HIR by using `Unevaluated` everywhere and later normalizing to `Evaluated` if the
-/// code is monomorphic enough for that.
-pub enum LazyConst<'tcx> {
-    Unevaluated(DefId, SubstsRef<'tcx>),
-    Evaluated(Const<'tcx>),
-}
-
-#[cfg(target_arch = "x86_64")]
-static_assert!(LAZY_CONST_SIZE: ::std::mem::size_of::<LazyConst<'static>>() == 56);
-
-impl<'tcx> LazyConst<'tcx> {
-    pub fn map_evaluated<R>(self, f: impl FnOnce(Const<'tcx>) -> Option<R>) -> Option<R> {
-        match self {
-            LazyConst::Evaluated(c) => f(c),
-            LazyConst::Unevaluated(..) => None,
-        }
-    }
-
-    pub fn assert_usize(self, tcx: TyCtxt<'_, '_, '_>) -> Option<u64> {
-        self.map_evaluated(|c| c.assert_usize(tcx))
-    }
-
-    #[inline]
-    pub fn unwrap_usize(&self, tcx: TyCtxt<'_, '_, '_>) -> u64 {
-        self.assert_usize(tcx).expect("expected `LazyConst` to contain a usize")
-    }
-
-    pub fn type_flags(&self) -> TypeFlags {
-        // FIXME(const_generics): incorporate substs flags.
-        let flags = match self {
-            LazyConst::Unevaluated(..) => {
-                TypeFlags::HAS_NORMALIZABLE_PROJECTION | TypeFlags::HAS_PROJECTION
-            }
-            LazyConst::Evaluated(c) => {
-                c.type_flags()
-            }
-        };
-
-        debug!("type_flags({:?}) = {:?}", self, flags);
-
-        flags
-    }
-}
-
 /// Typed constant value.
 #[derive(Copy, Clone, Debug, Hash, RustcEncodable, RustcDecodable,
          Eq, PartialEq, Ord, PartialOrd, HashStable)]
@@ -2256,36 +2210,9 @@ impl<'tcx> Const<'tcx> {
         self.assert_usize(tcx).unwrap_or_else(||
             bug!("expected constant usize, got {:#?}", self))
     }
-
-    pub fn type_flags(&self) -> TypeFlags {
-        let mut flags = self.ty.flags;
-
-        match self.val {
-            ConstValue::Param(_) => {
-                flags |= TypeFlags::HAS_FREE_LOCAL_NAMES;
-                flags |= TypeFlags::HAS_PARAMS;
-            }
-            ConstValue::Infer(infer) => {
-                flags |= TypeFlags::HAS_FREE_LOCAL_NAMES;
-                flags |= TypeFlags::HAS_CT_INFER;
-                match infer {
-                    InferConst::Fresh(_) |
-                    InferConst::Canonical(_, _) => {}
-                    InferConst::Var(_) => {
-                        flags |= TypeFlags::KEEP_IN_LOCAL_TCX;
-                    }
-                }
-            }
-            _ => {}
-        }
-
-        debug!("type_flags({:?}) = {:?}", self, flags);
-
-        flags
-    }
 }
 
-impl<'tcx> serialize::UseSpecializedDecodable for &'tcx LazyConst<'tcx> {}
+impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Const<'tcx> {}
 
 /// An inference variable for a const, for use in const generics.
 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd,
diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs
index 84642865614..3ba2c4cbf6c 100644
--- a/src/librustc/ty/subst.rs
+++ b/src/librustc/ty/subst.rs
@@ -26,7 +26,7 @@ use std::num::NonZeroUsize;
 #[derive(Copy, Clone, PartialEq, Eq, Hash)]
 pub struct Kind<'tcx> {
     ptr: NonZeroUsize,
-    marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>, &'tcx ty::LazyConst<'tcx>)>
+    marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>, &'tcx ty::Const<'tcx>)>
 }
 
 const TAG_MASK: usize = 0b11;
@@ -38,7 +38,7 @@ const CONST_TAG: usize = 0b10;
 pub enum UnpackedKind<'tcx> {
     Lifetime(ty::Region<'tcx>),
     Type(Ty<'tcx>),
-    Const(&'tcx ty::LazyConst<'tcx>),
+    Const(&'tcx ty::Const<'tcx>),
 }
 
 impl<'tcx> UnpackedKind<'tcx> {
@@ -104,8 +104,8 @@ impl<'tcx> From<Ty<'tcx>> for Kind<'tcx> {
     }
 }
 
-impl<'tcx> From<&'tcx ty::LazyConst<'tcx>> for Kind<'tcx> {
-    fn from(c: &'tcx ty::LazyConst<'tcx>) -> Kind<'tcx> {
+impl<'tcx> From<&'tcx ty::Const<'tcx>> for Kind<'tcx> {
+    fn from(c: &'tcx ty::Const<'tcx>) -> Kind<'tcx> {
         UnpackedKind::Const(c).pack()
     }
 }
@@ -208,12 +208,12 @@ impl<'a, 'gcx, 'tcx> InternalSubsts<'tcx> {
                 }
 
                 ty::GenericParamDefKind::Const => {
-                    tcx.mk_lazy_const(ty::LazyConst::Evaluated(ty::Const {
+                    tcx.mk_const(ty::Const {
                         val: ConstValue::Infer(
                             InferConst::Canonical(ty::INNERMOST, ty::BoundVar::from(param.index))
                         ),
                         ty: tcx.type_of(def_id),
-                    })).into()
+                    }).into()
                 }
             }
         })
@@ -304,7 +304,7 @@ impl<'a, 'gcx, 'tcx> InternalSubsts<'tcx> {
     }
 
     #[inline]
-    pub fn consts(&'a self) -> impl DoubleEndedIterator<Item = &'tcx ty::LazyConst<'tcx>> + 'a {
+    pub fn consts(&'a self) -> impl DoubleEndedIterator<Item = &'tcx ty::Const<'tcx>> + 'a {
         self.iter().filter_map(|k| {
             if let UnpackedKind::Const(ct) = k.unpack() {
                 Some(ct)
@@ -345,7 +345,7 @@ impl<'a, 'gcx, 'tcx> InternalSubsts<'tcx> {
     }
 
     #[inline]
-    pub fn const_at(&self, i: usize) -> &'tcx ty::LazyConst<'tcx> {
+    pub fn const_at(&self, i: usize) -> &'tcx ty::Const<'tcx> {
         if let UnpackedKind::Const(ct) = self[i].unpack() {
             ct
         } else {
@@ -522,16 +522,13 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for SubstFolder<'a, 'gcx, 'tcx> {
         return t1;
     }
 
-    fn fold_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> &'tcx ty::LazyConst<'tcx> {
+    fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
         if !c.needs_subst() {
             return c;
         }
 
-        if let ty::LazyConst::Evaluated(ty::Const {
-            val: ConstValue::Param(p),
-            ..
-        }) = c {
-            self.const_for_param(*p, c)
+        if let ConstValue::Param(p) = c.val {
+            self.const_for_param(p, c)
         } else {
             c.super_fold_with(self)
         }
@@ -564,8 +561,8 @@ impl<'a, 'gcx, 'tcx> SubstFolder<'a, 'gcx, 'tcx> {
     fn const_for_param(
         &self,
         p: ParamConst,
-        source_cn: &'tcx ty::LazyConst<'tcx>
-    ) -> &'tcx ty::LazyConst<'tcx> {
+        source_cn: &'tcx ty::Const<'tcx>
+    ) -> &'tcx ty::Const<'tcx> {
         // Look up the const in the substitutions. It really should be in there.
         let opt_cn = self.substs.get(p.index as usize).map(|k| k.unpack());
         let cn = match opt_cn {
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 65918a90821..4fb2bfb075c 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -497,10 +497,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
                     }) => {
                         !impl_generics.type_param(pt, self).pure_wrt_drop
                     }
-                    UnpackedKind::Const(&ty::LazyConst::Evaluated(ty::Const {
+                    UnpackedKind::Const(&ty::Const {
                         val: ConstValue::Param(ref pc),
                         ..
-                    })) => {
+                    }) => {
                         !impl_generics.const_param(pc, self).pure_wrt_drop
                     }
                     UnpackedKind::Lifetime(_) |
diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs
index d9f309ae58e..fa1eadf34ac 100644
--- a/src/librustc/ty/walk.rs
+++ b/src/librustc/ty/walk.rs
@@ -3,6 +3,7 @@
 
 use crate::ty::{self, Ty};
 use smallvec::{self, SmallVec};
+use crate::mir::interpret::ConstValue;
 
 // The TypeWalker's stack is hot enough that it's worth going to some effort to
 // avoid heap allocations.
@@ -74,9 +75,10 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) {
         ty::Placeholder(..) | ty::Bound(..) | ty::Foreign(..) => {
         }
         ty::Array(ty, len) => {
-            if let ty::LazyConst::Unevaluated(_, substs) = len {
+            if let ConstValue::Unevaluated(_, substs) = len.val {
                 stack.extend(substs.types().rev());
             }
+            stack.push(len.ty);
             stack.push(ty);
         }
         ty::Slice(ty) => {
diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs
index fa35416cdd4..7bfda6a6557 100644
--- a/src/librustc/ty/wf.rs
+++ b/src/librustc/ty/wf.rs
@@ -7,6 +7,7 @@ use crate::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable};
 use std::iter::once;
 use syntax_pos::Span;
 use crate::middle::lang_items;
+use crate::mir::interpret::ConstValue;
 
 /// Returns the set of obligations needed to make `ty` well-formed.
 /// If `ty` contains unresolved inference variables, this may include
@@ -203,8 +204,8 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> {
 
     /// Pushes the obligations required for an array length to be WF
     /// into `self.out`.
-    fn compute_array_len(&mut self, constant: ty::LazyConst<'tcx>) {
-        if let ty::LazyConst::Unevaluated(def_id, substs) = constant {
+    fn compute_array_len(&mut self, constant: ty::Const<'tcx>) {
+        if let ConstValue::Unevaluated(def_id, substs) = constant.val {
             let obligations = self.nominal_obligations(def_id, substs);
             self.out.extend(obligations);
 
diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs
index 2bb68dc687c..a1d44b228a5 100644
--- a/src/librustc_codegen_ssa/mir/constant.rs
+++ b/src/librustc_codegen_ssa/mir/constant.rs
@@ -2,7 +2,6 @@ use rustc::mir::interpret::ErrorHandled;
 use rustc_mir::const_eval::const_field;
 use rustc::mir;
 use rustc_data_structures::indexed_vec::Idx;
-use rustc::mir::interpret::GlobalId;
 use rustc::ty::{self, Ty};
 use rustc::ty::layout;
 use syntax::source_map::Span;
@@ -11,35 +10,27 @@ use crate::traits::*;
 use super::FunctionCx;
 
 impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
-    fn fully_evaluate(
+    pub fn eval_mir_constant(
         &mut self,
         bx: &Bx,
-        constant: &'tcx ty::LazyConst<'tcx>,
+        constant: &mir::Constant<'tcx>,
     ) -> Result<ty::Const<'tcx>, ErrorHandled> {
-        match *constant {
-            ty::LazyConst::Unevaluated(def_id, ref substs) => {
-                let tcx = bx.tcx();
-                let param_env = ty::ParamEnv::reveal_all();
-                let instance = ty::Instance::resolve(tcx, param_env, def_id, substs).unwrap();
-                let cid = GlobalId {
+        match constant.literal.val {
+            mir::interpret::ConstValue::Unevaluated(def_id, ref substs) => {
+                let substs = self.monomorphize(substs);
+                let instance = ty::Instance::resolve(
+                    bx.tcx(), ty::ParamEnv::reveal_all(), def_id, substs,
+                ).unwrap();
+                let cid = mir::interpret::GlobalId {
                     instance,
                     promoted: None,
                 };
-                tcx.const_eval(param_env.and(cid))
+                bx.tcx().const_eval(ty::ParamEnv::reveal_all().and(cid))
             },
-            ty::LazyConst::Evaluated(constant) => Ok(constant),
+            _ => Ok(*self.monomorphize(&constant.literal)),
         }
     }
 
-    pub fn eval_mir_constant(
-        &mut self,
-        bx: &Bx,
-        constant: &mir::Constant<'tcx>,
-    ) -> Result<ty::Const<'tcx>, ErrorHandled> {
-        let c = self.monomorphize(&constant.literal);
-        self.fully_evaluate(bx, c)
-    }
-
     /// process constant containing SIMD shuffle indices
     pub fn simd_shuffle_indices(
         &mut self,
diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs
index 55a1eb016e0..e17a6e7b03f 100644
--- a/src/librustc_codegen_ssa/mir/operand.rs
+++ b/src/librustc_codegen_ssa/mir/operand.rs
@@ -76,6 +76,7 @@ impl<'a, 'tcx: 'a, V: CodegenObject> OperandRef<'tcx, V> {
         }
 
         let val = match val.val {
+            ConstValue::Unevaluated(..) => bug!("unevaluated constant in `OperandRef::from_const`"),
             ConstValue::Param(_) => bug!("encountered a ConstValue::Param in codegen"),
             ConstValue::Infer(_) => bug!("encountered a ConstValue::Infer in codegen"),
             ConstValue::Scalar(x) => {
diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs
index 86134647324..14289381aef 100644
--- a/src/librustc_mir/borrow_check/error_reporting.rs
+++ b/src/librustc_mir/borrow_check/error_reporting.rs
@@ -1505,10 +1505,10 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         debug!("add_moved_or_invoked_closure_note: terminator={:?}", terminator);
         if let TerminatorKind::Call {
             func: Operand::Constant(box Constant {
-                literal: ty::LazyConst::Evaluated(ty::Const {
+                literal: ty::Const {
                     ty: &ty::TyS { sty: ty::TyKind::FnDef(id, _), ..  },
                     ..
-                }),
+                },
                 ..
             }),
             args,
diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs
index 65703adfdff..b8dae98ec64 100644
--- a/src/librustc_mir/borrow_check/mutability_errors.rs
+++ b/src/librustc_mir/borrow_check/mutability_errors.rs
@@ -471,13 +471,13 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                             Terminator {
                                 kind: TerminatorKind::Call {
                                     func: Operand::Constant(box Constant {
-                                        literal: ty::LazyConst::Evaluated(Const {
+                                        literal: Const {
                                             ty: &TyS {
                                                 sty: TyKind::FnDef(id, substs),
                                                 ..
                                             },
                                             ..
-                                        }),
+                                        },
                                         ..
                                     }),
                                     ..
diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs
index 0a0a88e6942..58e567c39a9 100644
--- a/src/librustc_mir/borrow_check/nll/renumber.rs
+++ b/src/librustc_mir/borrow_check/nll/renumber.rs
@@ -80,7 +80,7 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
         debug!("visit_region: region={:?}", region);
     }
 
-    fn visit_const(&mut self, constant: &mut &'tcx ty::LazyConst<'tcx>, _location: Location) {
+    fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, _location: Location) {
         *constant = self.renumber_regions(&*constant);
     }
 
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index 5b444ab9690..25a3160a498 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -28,7 +28,7 @@ use rustc::infer::canonical::QueryRegionConstraint;
 use rustc::infer::outlives::env::RegionBoundPairs;
 use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin};
 use rustc::infer::type_variable::TypeVariableOrigin;
-use rustc::mir::interpret::EvalErrorKind::BoundsCheck;
+use rustc::mir::interpret::{EvalErrorKind::BoundsCheck, ConstValue};
 use rustc::mir::tcx::PlaceTy;
 use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext, NonMutatingUseContext};
 use rustc::mir::*;
@@ -296,38 +296,34 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> {
                 );
             }
         } else {
-            match *constant.literal {
-                ty::LazyConst::Unevaluated(def_id, substs) => {
-                    if let Err(terr) = self.cx.fully_perform_op(
-                        location.to_locations(),
-                        ConstraintCategory::Boring,
-                        self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
-                            constant.ty, def_id, UserSubsts { substs, user_self_ty: None },
-                        )),
-                    ) {
-                        span_mirbug!(
-                            self,
-                            constant,
-                            "bad constant type {:?} ({:?})",
-                            constant,
-                            terr
-                        );
-                    }
-                }
-                ty::LazyConst::Evaluated(lit) => {
-                    if let ty::FnDef(def_id, substs) = lit.ty.sty {
-                        let tcx = self.tcx();
-
-                        let instantiated_predicates = tcx
-                            .predicates_of(def_id)
-                            .instantiate(tcx, substs);
-                        self.cx.normalize_and_prove_instantiated_predicates(
-                            instantiated_predicates,
-                            location.to_locations(),
-                        );
-                    }
+            if let ConstValue::Unevaluated(def_id, substs) = constant.literal.val {
+                if let Err(terr) = self.cx.fully_perform_op(
+                    location.to_locations(),
+                    ConstraintCategory::Boring,
+                    self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
+                        constant.ty, def_id, UserSubsts { substs, user_self_ty: None },
+                    )),
+                ) {
+                    span_mirbug!(
+                        self,
+                        constant,
+                        "bad constant type {:?} ({:?})",
+                        constant,
+                        terr
+                    );
                 }
             }
+            if let ty::FnDef(def_id, substs) = constant.literal.ty.sty {
+                let tcx = self.tcx();
+
+                let instantiated_predicates = tcx
+                    .predicates_of(def_id)
+                    .instantiate(tcx, substs);
+                self.cx.normalize_and_prove_instantiated_predicates(
+                    instantiated_predicates,
+                    location.to_locations(),
+                );
+            }
         }
     }
 
@@ -418,10 +414,11 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
             constant, location
         );
 
-        let literal = match constant.literal {
-            ty::LazyConst::Evaluated(lit) => lit,
-            ty::LazyConst::Unevaluated(..) => return,
-        };
+        let literal = constant.literal;
+
+        if let ConstValue::Unevaluated(..) = literal.val {
+            return;
+        }
 
         debug!("sanitize_constant: expected_ty={:?}", literal.ty);
 
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs
index f1a82ecef1b..9e12a7e6fa9 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir/build/expr/as_rvalue.rs
@@ -275,13 +275,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                             span: expr_span,
                             ty: this.hir.tcx().types.u32,
                             user_ty: None,
-                            literal: this.hir.tcx().mk_lazy_const(ty::LazyConst::Evaluated(
+                            literal: this.hir.tcx().mk_const(
                                 ty::Const::from_bits(
                                     this.hir.tcx(),
                                     0,
                                     ty::ParamEnv::empty().and(this.hir.tcx().types.u32),
                                 ),
-                            )),
+                            ),
                         }));
                         box AggregateKind::Generator(closure_id, substs, movability)
                     }
diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs
index 72b92444dec..0c93984fda8 100644
--- a/src/librustc_mir/build/matches/test.rs
+++ b/src/librustc_mir/build/matches/test.rs
@@ -299,7 +299,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     }
                     let eq_def_id = self.hir.tcx().lang_items().eq_trait().unwrap();
                     let (mty, method) = self.hir.trait_method(eq_def_id, "eq", ty, &[ty.into()]);
-                    let method = self.hir.tcx().mk_lazy_const(ty::LazyConst::Evaluated(method));
+                    let method = self.hir.tcx().mk_const(method);
 
                     let re_erased = self.hir.tcx().types.re_erased;
                     // take the argument by reference
diff --git a/src/librustc_mir/build/misc.rs b/src/librustc_mir/build/misc.rs
index 2692c24806f..d76d3765ac7 100644
--- a/src/librustc_mir/build/misc.rs
+++ b/src/librustc_mir/build/misc.rs
@@ -33,7 +33,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             span,
             ty,
             user_ty: None,
-            literal: self.hir.tcx().mk_lazy_const(ty::LazyConst::Evaluated(literal)),
+            literal: self.hir.tcx().mk_const(literal),
         };
         Operand::Constant(constant)
     }
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index c8e48dea1f3..ec8c62bb9b4 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -201,7 +201,7 @@ impl<'a, 'gcx: 'tcx, 'tcx> MutVisitor<'tcx> for GlobalizeMir<'a, 'gcx> {
         }
     }
 
-    fn visit_const(&mut self, constant: &mut &'tcx ty::LazyConst<'tcx>, _: Location) {
+    fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, _: Location) {
         if let Some(lifted) = self.tcx.lift(constant) {
             *constant = lifted;
         } else {
diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs
index 71d9398c686..79a3e0c5ee2 100644
--- a/src/librustc_mir/const_eval.rs
+++ b/src/librustc_mir/const_eval.rs
@@ -478,7 +478,7 @@ pub fn const_field<'a, 'tcx>(
     trace!("const_field: {:?}, {:?}", field, value);
     let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env);
     // get the operand again
-    let op = ecx.const_to_op(value, None).unwrap();
+    let op = ecx.eval_const_to_op(value, None).unwrap();
     // downcast
     let down = match variant {
         None => op,
@@ -500,7 +500,7 @@ pub fn const_variant_index<'a, 'tcx>(
 ) -> VariantIdx {
     trace!("const_variant_index: {:?}", val);
     let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env);
-    let op = ecx.const_to_op(val, None).unwrap();
+    let op = ecx.eval_const_to_op(val, None).unwrap();
     ecx.read_discriminant(op).unwrap().1
 }
 
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index c8c6d73d453..b83f048114b 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -342,9 +342,9 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         }
 
         hir::ExprKind::Lit(ref lit) => ExprKind::Literal {
-            literal: cx.tcx.mk_lazy_const(ty::LazyConst::Evaluated(
+            literal: cx.tcx.mk_const(
                 cx.const_eval_literal(&lit.node, expr_ty, lit.span, false)
-            )),
+            ),
             user_ty: None,
         },
 
@@ -442,9 +442,9 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             } else {
                 if let hir::ExprKind::Lit(ref lit) = arg.node {
                     ExprKind::Literal {
-                        literal: cx.tcx.mk_lazy_const(ty::LazyConst::Evaluated(
+                        literal: cx.tcx.mk_const(
                             cx.const_eval_literal(&lit.node, expr_ty, lit.span, true)
-                        )),
+                        ),
                         user_ty: None,
                     }
                 } else {
@@ -693,26 +693,29 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                 };
 
                 let source = if let Some((did, offset, var_ty)) = var {
-                    let mk_lazy_const = |literal| Expr {
+                    let mk_const = |literal| Expr {
                         temp_lifetime,
                         ty: var_ty,
                         span: expr.span,
                         kind: ExprKind::Literal {
-                            literal: cx.tcx.mk_lazy_const(literal),
+                            literal: cx.tcx.mk_const(literal),
                             user_ty: None
                         },
                     }.to_ref();
-                    let offset = mk_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_bits(
+                    let offset = mk_const(ty::Const::from_bits(
                         cx.tcx,
                         offset as u128,
                         cx.param_env.and(var_ty),
-                    )));
+                    ));
                     match did {
                         Some(did) => {
                             // in case we are offsetting from a computed discriminant
                             // and not the beginning of discriminants (which is always `0`)
                             let substs = InternalSubsts::identity_for_item(cx.tcx(), did);
-                            let lhs = mk_lazy_const(ty::LazyConst::Unevaluated(did, substs));
+                            let lhs = mk_const(ty::Const {
+                                val: ConstValue::Unevaluated(did, substs),
+                                ty: var_ty,
+                            });
                             let bin = ExprKind::Binary {
                                 op: BinOp::Add,
                                 lhs,
@@ -852,9 +855,9 @@ fn method_callee<'a, 'gcx, 'tcx>(
         ty,
         span,
         kind: ExprKind::Literal {
-            literal: cx.tcx().mk_lazy_const(ty::LazyConst::Evaluated(
+            literal: cx.tcx().mk_const(
                 ty::Const::zero_sized(ty)
-            )),
+            ),
             user_ty,
         },
     }
@@ -914,9 +917,9 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             let user_ty = user_substs_applied_to_def(cx, expr.hir_id, &def);
             debug!("convert_path_expr: user_ty={:?}", user_ty);
             ExprKind::Literal {
-                literal: cx.tcx.mk_lazy_const(ty::LazyConst::Evaluated(ty::Const::zero_sized(
+                literal: cx.tcx.mk_const(ty::Const::zero_sized(
                     cx.tables().node_type(expr.hir_id),
-                ))),
+                )),
                 user_ty,
             }
         }
@@ -930,11 +933,11 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             let name = cx.tcx.hir().name(node_id).as_interned_str();
             let val = ConstValue::Param(ty::ParamConst::new(index, name));
             ExprKind::Literal {
-                literal: cx.tcx.mk_lazy_const(
-                    ty::LazyConst::Evaluated(ty::Const {
+                literal: cx.tcx.mk_const(
+                    ty::Const {
                         val,
                         ty: cx.tables().node_type(expr.hir_id),
-                    })
+                    }
                 ),
                 user_ty: None,
             }
@@ -945,7 +948,10 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             let user_ty = user_substs_applied_to_def(cx, expr.hir_id, &def);
             debug!("convert_path_expr: (const) user_ty={:?}", user_ty);
             ExprKind::Literal {
-                literal: cx.tcx.mk_lazy_const(ty::LazyConst::Unevaluated(def_id, substs)),
+                literal: cx.tcx.mk_const(ty::Const {
+                    val: ConstValue::Unevaluated(def_id, substs),
+                    ty: cx.tcx.type_of(def_id),
+                }),
                 user_ty,
             }
         },
diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs
index c0f3989b4ba..71c6489d63f 100644
--- a/src/librustc_mir/hair/cx/mod.rs
+++ b/src/librustc_mir/hair/cx/mod.rs
@@ -106,8 +106,8 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
         self.tcx.types.usize
     }
 
-    pub fn usize_literal(&mut self, value: u64) -> &'tcx ty::LazyConst<'tcx> {
-        self.tcx.mk_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_usize(self.tcx, value)))
+    pub fn usize_literal(&mut self, value: u64) -> &'tcx ty::Const<'tcx> {
+        self.tcx.mk_const(ty::Const::from_usize(self.tcx, value))
     }
 
     pub fn bool_ty(&mut self) -> Ty<'tcx> {
@@ -118,12 +118,12 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> {
         self.tcx.mk_unit()
     }
 
-    pub fn true_literal(&mut self) -> &'tcx ty::LazyConst<'tcx> {
-        self.tcx.mk_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_bool(self.tcx, true)))
+    pub fn true_literal(&mut self) -> &'tcx ty::Const<'tcx> {
+        self.tcx.mk_const(ty::Const::from_bool(self.tcx, true))
     }
 
-    pub fn false_literal(&mut self) -> &'tcx ty::LazyConst<'tcx> {
-        self.tcx.mk_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_bool(self.tcx, false)))
+    pub fn false_literal(&mut self) -> &'tcx ty::Const<'tcx> {
+        self.tcx.mk_const(ty::Const::from_bool(self.tcx, false))
     }
 
     pub fn const_eval_literal(
diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs
index 385249ec1c1..3a38876bb68 100644
--- a/src/librustc_mir/hair/mod.rs
+++ b/src/librustc_mir/hair/mod.rs
@@ -9,7 +9,7 @@ use rustc::hir::def_id::DefId;
 use rustc::infer::canonical::Canonical;
 use rustc::middle::region;
 use rustc::ty::subst::SubstsRef;
-use rustc::ty::{AdtDef, UpvarSubsts, Ty, Const, LazyConst, UserType};
+use rustc::ty::{AdtDef, UpvarSubsts, Ty, Const, UserType};
 use rustc::ty::layout::VariantIdx;
 use rustc::hir;
 use syntax_pos::Span;
@@ -289,7 +289,7 @@ pub enum ExprKind<'tcx> {
         movability: Option<hir::GeneratorMovability>,
     },
     Literal {
-        literal: &'tcx LazyConst<'tcx>,
+        literal: &'tcx Const<'tcx>,
         user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
     },
     InlineAsm {
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs
index 44bcb9de0e1..88d1eb2ee0b 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir/hair/pattern/_match.rs
@@ -222,7 +222,7 @@ impl<'a, 'tcx> LiteralExpander<'a, 'tcx> {
                 assert_eq!(t, u);
                 ConstValue::Slice(
                     Scalar::Ptr(p),
-                    n.map_evaluated(|val| val.val.try_to_scalar())
+                    n.val.try_to_scalar()
                         .unwrap()
                         .to_usize(&self.tcx)
                         .unwrap(),
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs
index ad7b45d8945..8614be8d407 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir/hair/pattern/mod.rs
@@ -13,7 +13,7 @@ use crate::hair::constant::*;
 use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
 use rustc::mir::{UserTypeProjection};
 use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
-use rustc::ty::{self, DefIdTree, Region, TyCtxt, AdtDef, Ty, Lift, UserType};
+use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, UserType, DefIdTree};
 use rustc::ty::{CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations};
 use rustc::ty::subst::{SubstsRef, Kind};
 use rustc::ty::layout::VariantIdx;
@@ -1233,9 +1233,6 @@ pub fn compare_const_vals<'a, 'gcx, 'tcx>(
         return fallback();
     }
 
-    let tcx = tcx.global_tcx();
-    let (a, b, ty) = (a, b, ty).lift_to_tcx(tcx).unwrap();
-
     // FIXME: This should use assert_bits(ty) instead of use_bits
     // but triggers possibly bugs due to mismatching of arrays and slices
     if let (Some(a), Some(b)) = (a.to_bits(tcx, ty), b.to_bits(tcx, ty)) {
@@ -1251,11 +1248,12 @@ pub fn compare_const_vals<'a, 'gcx, 'tcx>(
                 let r = ::rustc_apfloat::ieee::Double::from_bits(b);
                 l.partial_cmp(&r)
             }
-            ty::Int(_) => {
-                let layout = tcx.layout_of(ty).ok()?;
-                assert!(layout.abi.is_signed());
-                let a = sign_extend(a, layout.size);
-                let b = sign_extend(b, layout.size);
+            ty::Int(ity) => {
+                use rustc::ty::layout::{Integer, IntegerExt};
+                use syntax::attr::SignedInt;
+                let size = Integer::from_attr(&tcx, SignedInt(ity)).size();
+                let a = sign_extend(a, size);
+                let b = sign_extend(b, size);
                 Some((a as i128).cmp(&(b as i128)))
             }
             _ => Some(a.cmp(&b)),
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index 206eaaf1787..70511075e87 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -547,7 +547,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
             Move(ref place) =>
                 self.eval_place_to_op(place, layout)?,
 
-            Constant(ref constant) => self.eval_lazy_const_to_op(*constant.literal, layout)?,
+            Constant(ref constant) => self.eval_const_to_op(*constant.literal, layout)?,
         };
         trace!("{:?}: {:?}", mir_op, *op);
         Ok(op)
@@ -563,36 +563,13 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
             .collect()
     }
 
-    // Used when Miri runs into a constant, and by const propagation.
-    crate fn eval_lazy_const_to_op(
-        &self,
-        val: ty::LazyConst<'tcx>,
-        layout: Option<TyLayout<'tcx>>,
-    ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
-        trace!("const_to_op: {:?}", val);
-        match val {
-            ty::LazyConst::Unevaluated(def_id, substs) => {
-                let instance = self.resolve(def_id, substs)?;
-                return Ok(OpTy::from(self.const_eval_raw(GlobalId {
-                    instance,
-                    promoted: None,
-                })?));
-            },
-            ty::LazyConst::Evaluated(c) => self.const_to_op(c, layout),
-        }
-    }
-
     // Used when the miri-engine runs into a constant and for extracting information from constants
     // in patterns via the `const_eval` module
-    crate fn const_to_op(
+    crate fn eval_const_to_op(
         &self,
         val: ty::Const<'tcx>,
         layout: Option<TyLayout<'tcx>>,
     ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
-        let val = self.monomorphize(val)?;
-        let layout = from_known_layout(layout, || {
-            self.layout_of(val.ty)
-        })?;
         let op = match val.val {
             ConstValue::Param(_) | ConstValue::Infer(_) => bug!(),
             ConstValue::ByRef(ptr, alloc) => {
@@ -609,7 +586,17 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
                 )).with_default_tag(),
             ConstValue::Scalar(x) =>
                 Operand::Immediate(Immediate::Scalar(x.into())).with_default_tag(),
+            ConstValue::Unevaluated(def_id, substs) => {
+                let instance = self.resolve(def_id, substs)?;
+                return Ok(OpTy::from(self.const_eval_raw(GlobalId {
+                    instance,
+                    promoted: None,
+                })?));
+            },
         };
+        let layout = from_known_layout(layout, || {
+            self.layout_of(self.monomorphize(val.ty)?)
+        })?;
         Ok(OpTy {
             op,
             layout,
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index 307cee5d972..4fe47a9666a 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -381,7 +381,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             let param_env = ty::ParamEnv::reveal_all();
 
             if let Ok(val) = tcx.const_eval(param_env.and(cid)) {
-                collect_const(tcx, val, &mut neighbors);
+                collect_const(tcx, val, InternalSubsts::empty(), &mut neighbors);
             }
         }
         MonoItem::Fn(instance) => {
@@ -468,15 +468,7 @@ fn check_type_length_limit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                      instance: Instance<'tcx>)
 {
     let type_length = instance.substs.types().flat_map(|ty| ty.walk()).count();
-    let const_length = instance.substs.consts()
-        .flat_map(|ct| {
-            let ty = match ct {
-                ty::LazyConst::Evaluated(ct) => ct.ty,
-                ty::LazyConst::Unevaluated(def_id, _) => tcx.type_of(*def_id),
-            };
-            ty.walk()
-        })
-        .count();
+    let const_length = instance.substs.consts().flat_map(|ct| ct.ty.walk()).count();
     debug!(" => type length={}, const length={}", type_length, const_length);
 
     // Rust code can easily create exponentially-long types using only a
@@ -606,10 +598,10 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
         self.super_rvalue(rvalue, location);
     }
 
-    fn visit_const(&mut self, constant: &&'tcx ty::LazyConst<'tcx>, location: Location) {
+    fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, location: Location) {
         debug!("visiting const {:?} @ {:?}", *constant, location);
 
-        collect_lazy_const(self.tcx, constant, self.param_substs, self.output);
+        collect_const(self.tcx, **constant, self.param_substs, self.output);
 
         self.super_const(constant);
     }
@@ -1013,7 +1005,7 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> {
                 let param_env = ty::ParamEnv::reveal_all();
 
                 if let Ok(val) = self.tcx.const_eval(param_env.and(cid)) {
-                    collect_const(self.tcx, val, &mut self.output);
+                    collect_const(self.tcx, val, InternalSubsts::empty(), &mut self.output);
                 }
             }
             hir::ItemKind::Fn(..) => {
@@ -1224,7 +1216,7 @@ fn collect_neighbours<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             promoted: Some(i),
         };
         match tcx.const_eval(param_env.and(cid)) {
-            Ok(val) => collect_const(tcx, val, output),
+            Ok(val) => collect_const(tcx, val, instance.substs, output),
             Err(ErrorHandled::Reported) => {},
             Err(ErrorHandled::TooGeneric) => span_bug!(
                 mir.promoted[i].span, "collection encountered polymorphic constant",
@@ -1242,43 +1234,10 @@ fn def_id_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     output
 }
 
-fn collect_lazy_const<'a, 'tcx>(
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    constant: &ty::LazyConst<'tcx>,
-    param_substs: SubstsRef<'tcx>,
-    output: &mut Vec<MonoItem<'tcx>>,
-) {
-    let (def_id, substs) = match *constant {
-        ty::LazyConst::Evaluated(c) => return collect_const(tcx, c, output),
-        ty::LazyConst::Unevaluated(did, substs) => (did, substs),
-    };
-    let param_env = ty::ParamEnv::reveal_all();
-    let substs = tcx.subst_and_normalize_erasing_regions(
-        param_substs,
-        param_env,
-        &substs,
-    );
-    let instance = ty::Instance::resolve(tcx,
-                                        param_env,
-                                        def_id,
-                                        substs).unwrap();
-
-    let cid = GlobalId {
-        instance,
-        promoted: None,
-    };
-    match tcx.const_eval(param_env.and(cid)) {
-        Ok(val) => collect_const(tcx, val, output),
-        Err(ErrorHandled::Reported) => {},
-        Err(ErrorHandled::TooGeneric) => span_bug!(
-            tcx.def_span(def_id), "collection encountered polymorphic constant",
-        ),
-    }
-}
-
 fn collect_const<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
     constant: ty::Const<'tcx>,
+    param_substs: SubstsRef<'tcx>,
     output: &mut Vec<MonoItem<'tcx>>,
 ) {
     debug!("visiting const {:?}", constant);
@@ -1292,6 +1251,30 @@ fn collect_const<'a, 'tcx>(
                 collect_miri(tcx, id, output);
             }
         }
+        ConstValue::Unevaluated(did, substs) => {
+            let param_env = ty::ParamEnv::reveal_all();
+            let substs = tcx.subst_and_normalize_erasing_regions(
+                param_substs,
+                param_env,
+                &substs,
+            );
+            let instance = ty::Instance::resolve(tcx,
+                                                param_env,
+                                                did,
+                                                substs).unwrap();
+
+            let cid = GlobalId {
+                instance,
+                promoted: None,
+            };
+            match tcx.const_eval(param_env.and(cid)) {
+                Ok(val) => collect_const(tcx, val, param_substs, output),
+                Err(ErrorHandled::Reported) => {},
+                Err(ErrorHandled::TooGeneric) => span_bug!(
+                    tcx.def_span(did), "collection encountered polymorphic constant",
+                ),
+            }
+        }
         _ => {},
     }
 }
diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs
index 68d13bf2dcb..51ba690d3a1 100644
--- a/src/librustc_mir/monomorphize/item.rs
+++ b/src/librustc_mir/monomorphize/item.rs
@@ -3,7 +3,7 @@ use rustc::hir;
 use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::mir::interpret::ConstValue;
 use rustc::session::config::OptLevel;
-use rustc::ty::{self, Ty, TyCtxt, Const, ClosureSubsts, GeneratorSubsts, LazyConst, ParamConst};
+use rustc::ty::{self, Ty, TyCtxt, Const, ClosureSubsts, GeneratorSubsts, ParamConst};
 use rustc::ty::subst::{SubstsRef, InternalSubsts};
 use syntax::ast;
 use syntax::attr::InlineAttr;
@@ -395,21 +395,17 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> {
     }
 
     // FIXME(const_generics): handle debug printing.
-    pub fn push_const_name(&self, c: &LazyConst<'tcx>, output: &mut String, debug: bool) {
-        match c {
-            LazyConst::Unevaluated(..) => output.push_str("_: _"),
-            LazyConst::Evaluated(Const { ty, val }) => {
-                match val {
-                    ConstValue::Infer(..) => output.push_str("_"),
-                    ConstValue::Param(ParamConst { name, .. }) => {
-                        write!(output, "{}", name).unwrap();
-                    }
-                    _ => write!(output, "{:?}", c).unwrap(),
-                }
-                output.push_str(": ");
-                self.push_type_name(ty, output, debug);
+    pub fn push_const_name(&self, c: &Const<'tcx>, output: &mut String, debug: bool) {
+        match c.val {
+            ConstValue::Infer(..) => output.push_str("_"),
+            ConstValue::Param(ParamConst { name, .. }) => {
+                write!(output, "{}", name).unwrap();
             }
+            ConstValue::Unevaluated(..) => output.push_str("_: _"),
+            _ => write!(output, "{:?}", c).unwrap(),
         }
+        output.push_str(": ");
+        self.push_type_name(c.ty, output, debug);
     }
 
     pub fn push_def_path(&self,
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index 1c6b1450be8..f1fbc80edfb 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -458,9 +458,9 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
             span: self.span,
             ty: func_ty,
             user_ty: None,
-            literal: tcx.mk_lazy_const(ty::LazyConst::Evaluated(
+            literal: tcx.mk_const(
                 ty::Const::zero_sized(func_ty),
-            )),
+            ),
         });
 
         let ref_loc = self.make_place(
@@ -520,9 +520,9 @@ impl<'a, 'tcx> CloneShimBuilder<'a, 'tcx> {
             span: self.span,
             ty: self.tcx.types.usize,
             user_ty: None,
-            literal: self.tcx.mk_lazy_const(ty::LazyConst::Evaluated(
+            literal: self.tcx.mk_const(
                 ty::Const::from_usize(self.tcx, value),
-            )),
+            ),
         }
     }
 
@@ -762,9 +762,9 @@ fn build_call_shim<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 span,
                 ty,
                 user_ty: None,
-                literal: tcx.mk_lazy_const(ty::LazyConst::Evaluated(
+                literal: tcx.mk_const(
                     ty::Const::zero_sized(ty)
-                )),
+                ),
              }),
              vec![rcvr])
         }
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 23d8138efcc..d8169684420 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -253,7 +253,7 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
         source_info: SourceInfo,
     ) -> Option<Const<'tcx>> {
         self.ecx.tcx.span = source_info.span;
-        match self.ecx.eval_lazy_const_to_op(*c.literal, None) {
+        match self.ecx.eval_const_to_op(*c.literal, None) {
             Ok(op) => {
                 Some((op, c.span))
             },
diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs
index 32c027d90a0..d5098bc1db2 100644
--- a/src/librustc_mir/transform/elaborate_drops.rs
+++ b/src/librustc_mir/transform/elaborate_drops.rs
@@ -533,9 +533,9 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
             span,
             ty: self.tcx.types.bool,
             user_ty: None,
-            literal: self.tcx.mk_lazy_const(ty::LazyConst::Evaluated(
+            literal: self.tcx.mk_const(
                 ty::Const::from_bool(self.tcx, val),
-            )),
+            ),
         })))
     }
 
diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs
index 9494d4b1f6c..a853f8d92be 100644
--- a/src/librustc_mir/transform/erase_regions.rs
+++ b/src/librustc_mir/transform/erase_regions.rs
@@ -32,7 +32,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for EraseRegionsVisitor<'a, 'tcx> {
         *region = self.tcx.types.re_erased;
     }
 
-    fn visit_const(&mut self, constant: &mut &'tcx ty::LazyConst<'tcx>, _: Location) {
+    fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, _: Location) {
         *constant = self.tcx.erase_regions(constant);
     }
 
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index 1f59802f8c6..33645b57589 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -198,11 +198,11 @@ impl<'a, 'tcx> TransformVisitor<'a, 'tcx> {
             span: source_info.span,
             ty: self.tcx.types.u32,
             user_ty: None,
-            literal: self.tcx.mk_lazy_const(ty::LazyConst::Evaluated(ty::Const::from_bits(
+            literal: self.tcx.mk_const(ty::Const::from_bits(
                 self.tcx,
                 state_disc.into(),
                 ty::ParamEnv::empty().and(self.tcx.types.u32)
-            ))),
+            )),
         });
         Statement {
             source_info,
@@ -729,9 +729,9 @@ fn insert_panic_block<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
             span: mir.span,
             ty: tcx.types.bool,
             user_ty: None,
-            literal: tcx.mk_lazy_const(ty::LazyConst::Evaluated(
+            literal: tcx.mk_const(
                 ty::Const::from_bool(tcx, false),
-            )),
+            ),
         }),
         expected: true,
         msg: message,
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 001a61959c2..e96689809ad 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -16,6 +16,7 @@ use rustc::ty::{self, TyCtxt, Ty, TypeFoldable};
 use rustc::ty::cast::CastTy;
 use rustc::ty::query::Providers;
 use rustc::mir::*;
+use rustc::mir::interpret::ConstValue;
 use rustc::mir::traversal::ReversePostorder;
 use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext, NonMutatingUseContext};
 use rustc::middle::lang_items;
@@ -199,12 +200,12 @@ trait Qualif {
             Operand::Move(ref place) => Self::in_place(cx, place),
 
             Operand::Constant(ref constant) => {
-                if let ty::LazyConst::Unevaluated(def_id, _) = constant.literal {
+                if let ConstValue::Unevaluated(def_id, _) = constant.literal.val {
                     // Don't peek inside trait associated constants.
-                    if cx.tcx.trait_of_item(*def_id).is_some() {
+                    if cx.tcx.trait_of_item(def_id).is_some() {
                         Self::in_any_value_of_ty(cx, constant.ty).unwrap_or(false)
                     } else {
-                        let (bits, _) = cx.tcx.at(constant.span).mir_const_qualif(*def_id);
+                        let (bits, _) = cx.tcx.at(constant.span).mir_const_qualif(def_id);
 
                         let qualif = PerQualif::decode_from_bits(bits).0[Self::IDX];
 
diff --git a/src/librustc_mir/transform/simplify_branches.rs b/src/librustc_mir/transform/simplify_branches.rs
index 3c4d1227a69..db73e829c53 100644
--- a/src/librustc_mir/transform/simplify_branches.rs
+++ b/src/librustc_mir/transform/simplify_branches.rs
@@ -30,7 +30,7 @@ impl MirPass for SimplifyBranches {
                     discr: Operand::Constant(ref c), switch_ty, ref values, ref targets, ..
                 } => {
                     let switch_ty = ParamEnv::empty().and(switch_ty);
-                    let constant = c.literal.map_evaluated(|c| c.assert_bits(tcx, switch_ty));
+                    let constant = c.literal.assert_bits(tcx, switch_ty);
                     if let Some(constant) = constant {
                         let (otherwise, targets) = targets.split_last().unwrap();
                         let mut ret = TerminatorKind::Goto { target: *otherwise };
@@ -47,7 +47,7 @@ impl MirPass for SimplifyBranches {
                 },
                 TerminatorKind::Assert {
                     target, cond: Operand::Constant(ref c), expected, ..
-                } if (c.literal.map_evaluated(|e| e.assert_bool(tcx)) == Some(true)) == expected =>
+                } if (c.literal.assert_bool(tcx) == Some(true)) == expected =>
                     TerminatorKind::Goto { target },
                 TerminatorKind::FalseEdges { real_target, .. } => {
                     TerminatorKind::Goto { target: real_target }
diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs
index 26fa8d6d1f0..37b38338ab9 100644
--- a/src/librustc_mir/util/elaborate_drops.rs
+++ b/src/librustc_mir/util/elaborate_drops.rs
@@ -966,9 +966,9 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D>
             span: self.source_info.span,
             ty: self.tcx().types.usize,
             user_ty: None,
-            literal: self.tcx().mk_lazy_const(ty::LazyConst::Evaluated(
+            literal: self.tcx().mk_const(
                 ty::Const::from_usize(self.tcx(), val.into())
-            )),
+            ),
         })
     }
 
diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs
index c7c77d351a7..4663f90eb3e 100644
--- a/src/librustc_mir/util/pretty.rs
+++ b/src/librustc_mir/util/pretty.rs
@@ -417,21 +417,12 @@ impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for ExtraComments<'cx, 'gcx, 'tcx> {
         self.push(&format!("+ literal: {:?}", literal));
     }
 
-    fn visit_const(&mut self, constant: &&'tcx ty::LazyConst<'tcx>, _: Location) {
+    fn visit_const(&mut self, constant: &&'tcx ty::Const<'tcx>, _: Location) {
         self.super_const(constant);
-        match constant {
-            ty::LazyConst::Evaluated(constant) => {
-                let ty::Const { ty, val, .. } = constant;
-                self.push("ty::Const");
-                self.push(&format!("+ ty: {:?}", ty));
-                self.push(&format!("+ val: {:?}", val));
-            },
-            ty::LazyConst::Unevaluated(did, substs) => {
-                self.push("ty::LazyConst::Unevaluated");
-                self.push(&format!("+ did: {:?}", did));
-                self.push(&format!("+ substs: {:?}", substs));
-            },
-        }
+        let ty::Const { ty, val, .. } = constant;
+        self.push("ty::Const");
+        self.push(&format!("+ ty: {:?}", ty));
+        self.push(&format!("+ val: {:?}", val));
     }
 
     fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
diff --git a/src/librustc_traits/chalk_context/mod.rs b/src/librustc_traits/chalk_context/mod.rs
index 6420f20a3ea..334f510d10d 100644
--- a/src/librustc_traits/chalk_context/mod.rs
+++ b/src/librustc_traits/chalk_context/mod.rs
@@ -288,13 +288,10 @@ impl context::ContextOps<ChalkArenas<'gcx>> for ChalkContext<'cx, 'gcx> {
                     }
                     _ => false,
                 },
-                UnpackedKind::Const(ct) => match ct {
-                    ty::LazyConst::Evaluated(ty::Const {
-                        val: ConstValue::Infer(InferConst::Canonical(debruijn, bound_ct)),
-                        ..
-                    }) => {
-                        debug_assert_eq!(*debruijn, ty::INNERMOST);
-                        cvar == *bound_ct
+                UnpackedKind::Const(ct) => match ct.val {
+                    ConstValue::Infer(InferConst::Canonical(debruijn, bound_ct)) => {
+                        debug_assert_eq!(debruijn, ty::INNERMOST);
+                        cvar == bound_ct
                     }
                     _ => false,
                 }
diff --git a/src/librustc_traits/chalk_context/program_clauses.rs b/src/librustc_traits/chalk_context/program_clauses.rs
index 3f88d0e08b4..8d5d2b8a9a2 100644
--- a/src/librustc_traits/chalk_context/program_clauses.rs
+++ b/src/librustc_traits/chalk_context/program_clauses.rs
@@ -239,7 +239,7 @@ fn wf_clause_for_slice<'tcx>(tcx: ty::TyCtxt<'_, '_, 'tcx>) -> Clauses<'tcx> {
 
 fn wf_clause_for_array<'tcx>(
     tcx: ty::TyCtxt<'_, '_, 'tcx>,
-    length: &'tcx ty::LazyConst<'tcx>
+    length: &'tcx ty::Const<'tcx>
 ) -> Clauses<'tcx> {
     let ty = generic_types::bound(tcx, 0);
     let array_ty = tcx.mk_ty(ty::Array(ty, length));
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 9ca75566b42..df8b1bcfe70 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -1870,16 +1870,19 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
         &self,
         ast_const: &hir::AnonConst,
         ty: Ty<'tcx>
-    ) -> &'tcx ty::LazyConst<'tcx> {
+    ) -> &'tcx ty::Const<'tcx> {
         debug!("ast_const_to_const(id={:?}, ast_const={:?})", ast_const.hir_id, ast_const);
 
         let tcx = self.tcx();
         let def_id = tcx.hir().local_def_id_from_hir_id(ast_const.hir_id);
 
-        let mut lazy_const = ty::LazyConst::Unevaluated(
-            def_id,
-            InternalSubsts::identity_for_item(tcx, def_id),
-        );
+        let mut const_ = ty::Const {
+            val: ConstValue::Unevaluated(
+                def_id,
+                InternalSubsts::identity_for_item(tcx, def_id),
+            ),
+            ty,
+        };
 
         let expr = &tcx.hir().body(ast_const.body).value;
         if let ExprKind::Path(ref qpath) = expr.node {
@@ -1891,15 +1894,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
                     let generics = tcx.generics_of(item_def_id);
                     let index = generics.param_def_id_to_index[&tcx.hir().local_def_id(node_id)];
                     let name = tcx.hir().name(node_id).as_interned_str();
-                    lazy_const = ty::LazyConst::Evaluated(ty::Const {
-                        val: ConstValue::Param(ty::ParamConst::new(index, name)),
-                        ty,
-                    })
+                    const_.val = ConstValue::Param(ty::ParamConst::new(index, name));
                 }
             }
         };
 
-        tcx.mk_lazy_const(lazy_const)
+        tcx.mk_const(const_)
     }
 
     pub fn impl_trait_ty_to_ty(
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index fa4bb02189f..ba6894b92fa 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -2424,7 +2424,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         ty
     }
 
-    pub fn to_const(&self, ast_c: &hir::AnonConst, ty: Ty<'tcx>) -> &'tcx ty::LazyConst<'tcx> {
+    pub fn to_const(&self, ast_c: &hir::AnonConst, ty: Ty<'tcx>) -> &'tcx ty::Const<'tcx> {
         AstConv::ast_const_to_const(self, ast_c, ty)
     }
 
@@ -4594,7 +4594,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 if element_ty.references_error() {
                     tcx.types.err
                 } else if let Ok(count) = count {
-                    tcx.mk_ty(ty::Array(t, tcx.mk_lazy_const(ty::LazyConst::Evaluated(count))))
+                    tcx.mk_ty(ty::Array(t, tcx.mk_const(count)))
                 } else {
                     tcx.types.err
                 }
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 1f7e05de18b..0675feade53 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -506,11 +506,8 @@ fn check_where_clauses<'a, 'gcx, 'fcx, 'tcx>(
                 true
             }
 
-            fn visit_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> bool {
-                if let ty::LazyConst::Evaluated(ty::Const {
-                    val: ConstValue::Param(param),
-                    ..
-                }) = c {
+            fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
+                if let ConstValue::Param(param) = c.val {
                     self.params.insert(param.index);
                 }
                 c.super_visit_with(self)
@@ -678,11 +675,8 @@ fn check_existential_types<'a, 'fcx, 'gcx, 'tcx>(
                                     }
                                 }
 
-                                ty::subst::UnpackedKind::Const(ct) => match ct {
-                                    ty::LazyConst::Evaluated(ty::Const {
-                                        val: ConstValue::Param(_),
-                                        ..
-                                    }) => {}
+                                ty::subst::UnpackedKind::Const(ct) => match ct.val {
+                                    ConstValue::Param(_) => {}
                                     _ => {
                                         tcx.sess
                                             .struct_span_err(
diff --git a/src/librustc_typeck/constrained_type_params.rs b/src/librustc_typeck/constrained_type_params.rs
index 4b922c34038..c8687f5e455 100644
--- a/src/librustc_typeck/constrained_type_params.rs
+++ b/src/librustc_typeck/constrained_type_params.rs
@@ -78,12 +78,9 @@ impl<'tcx> TypeVisitor<'tcx> for ParameterCollector {
         false
     }
 
-    fn visit_const(&mut self, c: &'tcx ty::LazyConst<'tcx>) -> bool {
-        if let ty::LazyConst::Evaluated(ty::Const {
-            val: ConstValue::Param(data),
-            ..
-        }) = c {
-            self.parameters.push(Parameter::from(*data));
+    fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool {
+        if let ConstValue::Param(data) = c.val {
+            self.parameters.push(Parameter::from(data));
         }
         false
     }
diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs
index c18f9fd102f..20eae5d8835 100644
--- a/src/librustc_typeck/variance/constraints.rs
+++ b/src/librustc_typeck/variance/constraints.rs
@@ -452,7 +452,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
     fn add_constraints_from_const(
         &mut self,
         current: &CurrentItem,
-        ct: &ty::LazyConst<'tcx>,
+        ct: &ty::Const<'tcx>,
         variance: VarianceTermPtr<'a>
     ) {
         debug!(
@@ -461,11 +461,9 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
             variance
         );
 
-        if let ty::LazyConst::Evaluated(ct) = ct {
-            self.add_constraints_from_ty(current, ct.ty, variance);
-            if let ConstValue::Param(ref data) = ct.val {
-                self.add_constraint(current, data.index, variance);
-            }
+        self.add_constraints_from_ty(current, ct.ty, variance);
+        if let ConstValue::Param(ref data) = ct.val {
+            self.add_constraint(current, data.index, variance);
         }
     }
 
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 3aea661f6be..c51c8027de6 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -16,7 +16,7 @@ use rustc::infer::region_constraints::{RegionConstraintData, Constraint};
 use rustc::middle::resolve_lifetime as rl;
 use rustc::middle::lang_items;
 use rustc::middle::stability;
-use rustc::mir::interpret::GlobalId;
+use rustc::mir::interpret::{GlobalId, ConstValue};
 use rustc::hir::{self, GenericArg, HirVec};
 use rustc::hir::def::{self, Def, CtorKind};
 use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
@@ -2551,7 +2551,7 @@ impl Clean<Type> for hir::Ty {
                     promoted: None
                 };
                 let length = match cx.tcx.const_eval(param_env.and(cid)) {
-                    Ok(length) => print_const(cx, ty::LazyConst::Evaluated(length)),
+                    Ok(length) => print_const(cx, length),
                     Err(_) => "_".to_string(),
                 };
                 Array(box ty.clean(cx), length)
@@ -2739,14 +2739,14 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
             ty::Slice(ty) => Slice(box ty.clean(cx)),
             ty::Array(ty, n) => {
                 let mut n = *cx.tcx.lift(&n).expect("array lift failed");
-                if let ty::LazyConst::Unevaluated(def_id, substs) = n {
+                if let ConstValue::Unevaluated(def_id, substs) = n.val {
                     let param_env = cx.tcx.param_env(def_id);
                     let cid = GlobalId {
                         instance: ty::Instance::new(def_id, substs),
                         promoted: None
                     };
                     if let Ok(new_n) = cx.tcx.const_eval(param_env.and(cid)) {
-                        n = ty::LazyConst::Evaluated(new_n);
+                        n = new_n;
                     }
                 };
                 let n = print_const(cx, n);
@@ -3900,16 +3900,16 @@ fn name_from_pat(p: &hir::Pat) -> String {
     }
 }
 
-fn print_const(cx: &DocContext<'_>, n: ty::LazyConst<'_>) -> String {
-    match n {
-        ty::LazyConst::Unevaluated(def_id, _) => {
+fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
+    match n.val {
+        ConstValue::Unevaluated(def_id, _) => {
             if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(def_id) {
                 print_const_expr(cx, cx.tcx.hir().body_owned_by(hir_id))
             } else {
                 inline::print_inlined_const(cx, def_id)
             }
         },
-        ty::LazyConst::Evaluated(n) => {
+        _ => {
             let mut s = String::new();
             ::rustc::mir::fmt_const_val(&mut s, n).expect("fmt_const_val failed");
             // array lengths are obviously usize