about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorAlexander Regueiro <alexreg@me.com>2018-01-02 23:22:09 +0000
committerOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>2018-03-08 08:09:01 +0100
commitb2b101befcfe1ca4ea57862675df0de5ca7b15bd (patch)
treed314f6ba6112589a114463de58929b7986271e47 /src
parent4c9b1b13ddc3f3120bb7aee106a261613dfcb000 (diff)
Prepare for using miri in trans
Diffstat (limited to 'src')
-rw-r--r--src/librustc/dep_graph/dep_node.rs8
-rw-r--r--src/librustc/ich/impls_mir.rs2
-rw-r--r--src/librustc/ich/impls_ty.rs8
-rw-r--r--src/librustc/traits/fulfill.rs34
-rw-r--r--src/librustc/traits/project.rs40
-rw-r--r--src/librustc/traits/select.rs24
-rw-r--r--src/librustc/ty/maps/config.rs7
-rw-r--r--src/librustc/ty/maps/keys.rs10
-rw-r--r--src/librustc/ty/maps/mod.rs5
-rw-r--r--src/librustc/ty/mod.rs16
-rw-r--r--src/librustc/ty/relate.rs32
-rw-r--r--src/librustc/ty/structural_impls.rs52
-rw-r--r--src/librustc_mir/const_eval/check.rs14
-rw-r--r--src/librustc_mir/const_eval/pattern.rs20
-rw-r--r--src/librustc_mir/hair/cx/expr.rs13
-rw-r--r--src/librustc_mir/interpret/const_eval.rs109
-rw-r--r--src/librustc_typeck/check/mod.rs13
-rw-r--r--src/librustc_typeck/collect.rs9
18 files changed, 286 insertions, 130 deletions
diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs
index ed46296389d..6824c015eab 100644
--- a/src/librustc/dep_graph/dep_node.rs
+++ b/src/librustc/dep_graph/dep_node.rs
@@ -60,15 +60,15 @@
 //! user of the `DepNode` API of having to know how to compute the expected
 //! fingerprint for a given set of node parameters.
 
+use mir::interpret::{GlobalId};
 use hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX};
 use hir::map::DefPathHash;
 use hir::{HirId, ItemLocalId};
 
-use ich::Fingerprint;
+use ich::{Fingerprint, StableHashingContext};
+use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
 use ty::{TyCtxt, Instance, InstanceDef, ParamEnv, ParamEnvAnd, PolyTraitRef, Ty};
 use ty::subst::Substs;
-use rustc_data_structures::stable_hasher::{StableHasher, HashStable};
-use ich::StableHashingContext;
 use std::fmt;
 use std::hash::Hash;
 use syntax_pos::symbol::InternedString;
@@ -518,7 +518,7 @@ define_dep_nodes!( <'tcx>
     [] TypeckTables(DefId),
     [] UsedTraitImports(DefId),
     [] HasTypeckTables(DefId),
-    [] ConstEval { param_env: ParamEnvAnd<'tcx, (DefId, &'tcx Substs<'tcx>)> },
+    [] ConstEval { param_env: ParamEnvAnd<'tcx, GlobalId<'tcx>> },
     [] CheckMatch(DefId),
     [] SymbolName(DefId),
     [] InstanceSymbolName { instance: Instance<'tcx> },
diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs
index 67b4cfb6fa7..40204943bb5 100644
--- a/src/librustc/ich/impls_mir.rs
+++ b/src/librustc/ich/impls_mir.rs
@@ -585,3 +585,5 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for mir::ClosureOutlivesSubjec
         }
     }
 }
+
+impl_stable_hash_for!(struct mir::interpret::GlobalId<'tcx> { instance, promoted });
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index 08a42e61ea0..a25741c95aa 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -926,13 +926,13 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for ty::InstanceDef<'gcx> {
             ty::InstanceDef::ClosureOnceShim { call_once } => {
                 call_once.hash_stable(hcx, hasher);
             }
-            ty::InstanceDef::DropGlue(def_id, t) => {
+            ty::InstanceDef::DropGlue(def_id, ty) => {
                 def_id.hash_stable(hcx, hasher);
-                t.hash_stable(hcx, hasher);
+                ty.hash_stable(hcx, hasher);
             }
-            ty::InstanceDef::CloneShim(def_id, t) => {
+            ty::InstanceDef::CloneShim(def_id, ty) => {
                 def_id.hash_stable(hcx, hasher);
-                t.hash_stable(hcx, hasher);
+                ty.hash_stable(hcx, hasher);
             }
         }
     }
diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs
index 2f3e19d92bc..2eeef70a14e 100644
--- a/src/librustc/traits/fulfill.rs
+++ b/src/librustc/traits/fulfill.rs
@@ -9,6 +9,9 @@
 // except according to those terms.
 
 use infer::{RegionObligation, InferCtxt};
+use middle::const_val::ConstEvalErr;
+use middle::const_val::ErrKind::TypeckError;
+use mir::interpret::GlobalId;
 use ty::{self, Ty, TypeFoldable, ToPolyTraitRef, ToPredicate};
 use ty::error::ExpectedFound;
 use rustc_data_structures::obligation_forest::{ObligationForest, Error};
@@ -514,17 +517,34 @@ fn process_predicate<'a, 'gcx, 'tcx>(
                 }
                 Some(param_env) => {
                     match selcx.tcx().lift_to_global(&substs) {
+                        Some(substs) => {
+                            let instance = ty::Instance::resolve(
+                                selcx.tcx().global_tcx(),
+                                param_env,
+                                def_id,
+                                substs,
+                            );
+                            if let Some(instance) = instance {
+                                let cid = GlobalId {
+                                    instance,
+                                    promoted: None,
+                                };
+                                match selcx.tcx().at(obligation.cause.span)
+                                                 .const_eval(param_env.and(cid)) {
+                                    Ok(_) => Ok(Some(vec![])),
+                                    Err(e) => Err(CodeSelectionError(ConstEvalFailure(e)))
+                                }
+                            } else {
+                                Err(CodeSelectionError(ConstEvalFailure(ConstEvalErr {
+                                    span: selcx.tcx().def_span(def_id),
+                                    kind: TypeckError,
+                                })))
+                            }
+                        },
                         None => {
                             pending_obligation.stalled_on = substs.types().collect();
                             Ok(None)
                         }
-                        Some(substs) => {
-                            match selcx.tcx().at(obligation.cause.span)
-                                             .const_eval(param_env.and((def_id, substs))) {
-                                Ok(_) => Ok(Some(vec![])),
-                                Err(e) => Err(CodeSelectionError(ConstEvalFailure(e)))
-                            }
-                        }
                     }
                 }
             }
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index 3fe72344e8f..a9dc4915743 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -29,6 +29,7 @@ use hir::def_id::DefId;
 use infer::{InferCtxt, InferOk};
 use infer::type_variable::TypeVariableOrigin;
 use middle::const_val::ConstVal;
+use mir::interpret::{GlobalId};
 use rustc_data_structures::snapshot_map::{Snapshot, SnapshotMap};
 use syntax::symbol::Symbol;
 use ty::subst::{Subst, Substs};
@@ -400,12 +401,17 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a,
 
     fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
         if let ConstVal::Unevaluated(def_id, substs) = constant.val {
-            if substs.needs_infer() {
-                let identity_substs = Substs::identity_for_item(self.tcx(), def_id);
-                let data = self.param_env.and((def_id, identity_substs));
-                match self.tcx().lift_to_global(&data) {
-                    Some(data) => {
-                        match self.tcx().const_eval(data) {
+            let tcx = self.selcx.tcx().global_tcx();
+            if let Some(param_env) = self.tcx().lift_to_global(&self.param_env) {
+                if substs.needs_infer() {
+                    let identity_substs = Substs::identity_for_item(tcx, def_id);
+                    let instance = ty::Instance::resolve(tcx, param_env, def_id, identity_substs);
+                    if let Some(instance) = instance {
+                        let cid = GlobalId {
+                            instance,
+                            promoted: None
+                        };
+                        match tcx.const_eval(param_env.and(cid)) {
                             Ok(evaluated) => {
                                 let evaluated = evaluated.subst(self.tcx(), substs);
                                 return self.fold_const(evaluated);
@@ -413,18 +419,20 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a,
                             Err(_) => {}
                         }
                     }
-                    None => {}
-                }
-            } else {
-                let data = self.param_env.and((def_id, substs));
-                match self.tcx().lift_to_global(&data) {
-                    Some(data) => {
-                        match self.tcx().const_eval(data) {
-                            Ok(evaluated) => return self.fold_const(evaluated),
-                            Err(_) => {}
+                } else {
+                    if let Some(substs) = self.tcx().lift_to_global(&substs) {
+                        let instance = ty::Instance::resolve(tcx, param_env, def_id, substs);
+                        if let Some(instance) = instance {
+                            let cid = GlobalId {
+                                instance,
+                                promoted: None
+                            };
+                            match tcx.const_eval(param_env.and(cid)) {
+                                Ok(evaluated) => return self.fold_const(evaluated),
+                                Err(_) => {}
+                            }
                         }
                     }
-                    None => {}
                 }
             }
         }
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 600b4a515f0..91d86394b01 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -42,6 +42,7 @@ use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
 use ty::fast_reject;
 use ty::relate::TypeRelation;
 use middle::lang_items;
+use mir::interpret::{GlobalId};
 
 use rustc_data_structures::bitvec::BitVector;
 use std::iter;
@@ -732,11 +733,26 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
             }
 
             ty::Predicate::ConstEvaluatable(def_id, substs) => {
-                match self.tcx().lift_to_global(&(obligation.param_env, substs)) {
+                let tcx = self.tcx();
+                match tcx.lift_to_global(&(obligation.param_env, substs)) {
                     Some((param_env, substs)) => {
-                        match self.tcx().const_eval(param_env.and((def_id, substs))) {
-                            Ok(_) => EvaluatedToOk,
-                            Err(_) => EvaluatedToErr
+                        let instance = ty::Instance::resolve(
+                            tcx.global_tcx(),
+                            param_env,
+                            def_id,
+                            substs,
+                        );
+                        if let Some(instance) = instance {
+                            let cid = GlobalId {
+                                instance,
+                                promoted: None
+                            };
+                            match self.tcx().const_eval(param_env.and(cid)) {
+                                Ok(_) => EvaluatedToOk,
+                                Err(_) => EvaluatedToErr
+                            }
+                        } else {
+                            EvaluatedToErr
                         }
                     }
                     None => {
diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs
index d880b022e2f..21affcbc9ed 100644
--- a/src/librustc/ty/maps/config.rs
+++ b/src/librustc/ty/maps/config.rs
@@ -10,9 +10,10 @@
 
 use dep_graph::SerializedDepNodeIndex;
 use hir::def_id::{CrateNum, DefId, DefIndex};
+use mir::interpret::{GlobalId};
 use ty::{self, Ty, TyCtxt};
-use ty::maps::queries;
 use ty::subst::Substs;
+use ty::maps::queries;
 
 use std::hash::Hash;
 use syntax_pos::symbol::InternedString;
@@ -152,8 +153,8 @@ impl<'tcx> QueryDescription<'tcx> for queries::reachable_set<'tcx> {
 }
 
 impl<'tcx> QueryDescription<'tcx> for queries::const_eval<'tcx> {
-    fn describe(tcx: TyCtxt, key: ty::ParamEnvAnd<'tcx, (DefId, &'tcx Substs<'tcx>)>) -> String {
-        format!("const-evaluating `{}`", tcx.item_path_str(key.value.0))
+    fn describe(tcx: TyCtxt, key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>) -> String {
+        format!("const-evaluating `{}`", tcx.item_path_str(key.value.instance.def.def_id()))
     }
 }
 
diff --git a/src/librustc/ty/maps/keys.rs b/src/librustc/ty/maps/keys.rs
index 3dd482ad164..8fb1ad0da82 100644
--- a/src/librustc/ty/maps/keys.rs
+++ b/src/librustc/ty/maps/keys.rs
@@ -53,6 +53,16 @@ impl<'tcx> Key for ty::Instance<'tcx> {
     }
 }
 
+impl<'tcx> Key for mir::interpret::GlobalId<'tcx> {
+    fn map_crate(&self) -> CrateNum {
+        self.instance.map_crate()
+    }
+
+    fn default_span(&self, tcx: TyCtxt) -> Span {
+        self.instance.default_span(tcx)
+    }
+}
+
 impl Key for CrateNum {
     fn map_crate(&self) -> CrateNum {
         *self
diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs
index 43a71f1c0d3..f41bdf61d9b 100644
--- a/src/librustc/ty/maps/mod.rs
+++ b/src/librustc/ty/maps/mod.rs
@@ -29,6 +29,7 @@ use middle::lang_items::{LanguageItems, LangItem};
 use middle::exported_symbols::{SymbolExportLevel, ExportedSymbol};
 use mir::mono::{CodegenUnit, Stats};
 use mir;
+use mir::interpret::{GlobalId};
 use session::{CompileResult, CrateDisambiguator};
 use session::config::OutputFilenames;
 use traits::Vtable;
@@ -210,7 +211,7 @@ define_maps! { <'tcx>
 
     /// Results of evaluating const items or constants embedded in
     /// other items (such as enum variant explicit discriminants).
-    [] fn const_eval: const_eval_dep_node(ty::ParamEnvAnd<'tcx, (DefId, &'tcx Substs<'tcx>)>)
+    [] fn const_eval: const_eval_dep_node(ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
         -> const_val::EvalResult<'tcx>,
 
     [] fn check_match: CheckMatch(DefId)
@@ -450,7 +451,7 @@ fn typeck_item_bodies_dep_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> {
     DepConstructor::TypeckBodiesKrate
 }
 
-fn const_eval_dep_node<'tcx>(param_env: ty::ParamEnvAnd<'tcx, (DefId, &'tcx Substs<'tcx>)>)
+fn const_eval_dep_node<'tcx>(param_env: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>)
                              -> DepConstructor<'tcx> {
     DepConstructor::ConstEval { param_env }
 }
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 8c955bf340e..02bf409f33f 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -26,7 +26,7 @@ use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangIte
 use middle::privacy::AccessLevels;
 use middle::resolve_lifetime::ObjectLifetimeDefault;
 use mir::Mir;
-use mir::interpret::{Value, PrimVal};
+use mir::interpret::{GlobalId, Value, PrimVal};
 use mir::GeneratorLayout;
 use session::CrateDisambiguator;
 use traits;
@@ -1835,7 +1835,12 @@ impl<'a, 'gcx, 'tcx> AdtDef {
             let mut discr = prev_discr.map_or(initial, |d| d.wrap_incr());
             if let VariantDiscr::Explicit(expr_did) = v.discr {
                 let substs = Substs::identity_for_item(tcx.global_tcx(), expr_did);
-                match tcx.const_eval(param_env.and((expr_did, substs))) {
+                let instance = ty::Instance::new(expr_did, substs);
+                let cid = GlobalId {
+                    instance,
+                    promoted: None
+                };
+                match tcx.const_eval(param_env.and(cid)) {
                     Ok(&ty::Const {
                         val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))),
                         ..
@@ -1885,7 +1890,12 @@ impl<'a, 'gcx, 'tcx> AdtDef {
                 }
                 ty::VariantDiscr::Explicit(expr_did) => {
                     let substs = Substs::identity_for_item(tcx.global_tcx(), expr_did);
-                    match tcx.const_eval(param_env.and((expr_did, substs))) {
+                    let instance = ty::Instance::new(expr_did, substs);
+                    let cid = GlobalId {
+                        instance,
+                        promoted: None
+                    };
+                    match tcx.const_eval(param_env.and(cid)) {
                         Ok(&ty::Const {
                             val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))),
                             ..
diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs
index 2cbe9da88b5..bae1ce31a5e 100644
--- a/src/librustc/ty/relate.rs
+++ b/src/librustc/ty/relate.rs
@@ -20,7 +20,7 @@ use ty::subst::{UnpackedKind, Substs};
 use ty::{self, Ty, TyCtxt, TypeFoldable};
 use ty::fold::{TypeVisitor, TypeFolder};
 use ty::error::{ExpectedFound, TypeError};
-use mir::interpret::{Value, PrimVal};
+use mir::interpret::{GlobalId, Value, PrimVal};
 use util::common::ErrorReported;
 use std::rc::Rc;
 use std::iter;
@@ -489,17 +489,29 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R,
                         let param_env = ty::ParamEnv::empty(Reveal::UserFacing);
                         match tcx.lift_to_global(&substs) {
                             Some(substs) => {
-                                match tcx.const_eval(param_env.and((def_id, substs))) {
-                                    Ok(&ty::Const {
-                                        val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))),
-                                        ..
-                                    }) => {
-                                        assert_eq!(b as u64 as u128, b);
-                                        return Ok(b as u64);
+                                let instance = ty::Instance::resolve(
+                                    tcx.global_tcx(),
+                                    param_env,
+                                    def_id,
+                                    substs,
+                                );
+                                if let Some(instance) = instance {
+                                    let cid = GlobalId {
+                                        instance,
+                                        promoted: None
+                                    };
+                                    match tcx.const_eval(param_env.and(cid)) {
+                                        Ok(&ty::Const {
+                                            val: ConstVal::Value(Value::ByVal(PrimVal::Bytes(b))),
+                                            ..
+                                        }) => {
+                                            assert_eq!(b as u64 as u128, b);
+                                            return Ok(b as u64);
+                                        }
+                                        _ => {}
                                     }
-                                    _ => {}
                                 }
-                            }
+                            },
                             None => {}
                         }
                         tcx.sess.delay_span_bug(tcx.def_span(def_id),
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index ad66cbd9eab..7cc509f6914 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -57,6 +57,7 @@ CopyImpls! {
     ::syntax::abi::Abi,
     ::hir::def_id::DefId,
     ::mir::Local,
+    ::mir::Promoted,
     ::traits::Reveal,
     ::syntax_pos::Span,
 }
@@ -589,7 +590,7 @@ impl<'a, 'tcx> Lift<'tcx> for ConstEvalErr<'a> {
 impl<'a, 'tcx> Lift<'tcx> for interpret::EvalError<'a> {
     type Lifted = interpret::EvalError<'tcx>;
     fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
-        use mir::interpret::EvalErrorKind::*;
+        use ::mir::interpret::EvalErrorKind::*;
         let kind = match self.kind {
             MachineError(ref err) => MachineError(err.clone()),
             FunctionPointerTyMismatch(a, b) => FunctionPointerTyMismatch(
@@ -744,6 +745,42 @@ impl<'a, 'tcx> Lift<'tcx> for ty::layout::LayoutError<'a> {
     }
 }
 
+impl<'a, 'tcx> Lift<'tcx> for ty::InstanceDef<'a> {
+    type Lifted = ty::InstanceDef<'tcx>;
+    fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
+        match *self {
+            ty::InstanceDef::Item(def_id) =>
+                Some(ty::InstanceDef::Item(def_id)),
+            ty::InstanceDef::Intrinsic(def_id) =>
+                Some(ty::InstanceDef::Intrinsic(def_id)),
+            ty::InstanceDef::FnPtrShim(def_id, ref ty) =>
+                Some(ty::InstanceDef::FnPtrShim(def_id, tcx.lift(ty)?)),
+            ty::InstanceDef::Virtual(def_id, n) =>
+                Some(ty::InstanceDef::Virtual(def_id, n)),
+            ty::InstanceDef::ClosureOnceShim { call_once } =>
+                Some(ty::InstanceDef::ClosureOnceShim { call_once }),
+            ty::InstanceDef::DropGlue(def_id, ref ty) =>
+                Some(ty::InstanceDef::DropGlue(def_id, tcx.lift(ty)?)),
+            ty::InstanceDef::CloneShim(def_id, ref ty) =>
+                Some(ty::InstanceDef::CloneShim(def_id, tcx.lift(ty)?)),
+        }
+    }
+}
+
+BraceStructLiftImpl! {
+    impl<'a, 'tcx> Lift<'tcx> for ty::Instance<'a> {
+        type Lifted = ty::Instance<'tcx>;
+        def, substs
+    }
+}
+
+BraceStructLiftImpl! {
+    impl<'a, 'tcx> Lift<'tcx> for interpret::GlobalId<'a> {
+        type Lifted = interpret::GlobalId<'tcx>;
+        instance, promoted
+    }
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // TypeFoldable implementations.
 //
@@ -945,6 +982,19 @@ impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> {
     }
 }
 
+impl<'tcx> TypeFoldable<'tcx> for interpret::GlobalId<'tcx> {
+    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+        Self {
+            instance: self.instance.fold_with(folder),
+            promoted: self.promoted
+        }
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        self.instance.visit_with(visitor)
+    }
+}
+
 impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
     fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
         let sty = match self.sty {
diff --git a/src/librustc_mir/const_eval/check.rs b/src/librustc_mir/const_eval/check.rs
index 70435c16ff7..a9508defdcd 100644
--- a/src/librustc_mir/const_eval/check.rs
+++ b/src/librustc_mir/const_eval/check.rs
@@ -12,7 +12,7 @@
 
 use rustc::mir::*;
 use rustc::mir::visit::Visitor;
-use rustc::mir::interpret::{Value, PrimVal};
+use rustc::mir::interpret::{Value, PrimVal, GlobalId};
 use rustc::middle::const_val::{ConstVal, ConstEvalErr, ErrKind};
 use rustc::traits;
 use interpret::{eval_body_as_integer, check_body};
@@ -41,7 +41,11 @@ pub fn check<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
     let instance = Instance::mono(tcx, def_id);
     for i in 0.. mir.promoted.len() {
         use rustc_data_structures::indexed_vec::Idx;
-        check_body(tcx, instance, Some(Promoted::new(i)), param_env);
+        let cid = GlobalId {
+            instance,
+            promoted: Some(Promoted::new(i)),
+        };
+        check_body(tcx, cid, param_env);
     }
 }
 
@@ -65,7 +69,11 @@ impl<'a, 'tcx> ConstErrVisitor<'a, 'tcx> {
             },
             Literal::Promoted { index } => {
                 let instance = Instance::mono(self.tcx, self.def_id);
-                eval_body_as_integer(self.tcx, param_env, instance, Some(index)).unwrap()
+                let cid = GlobalId {
+                    instance,
+                    promoted: Some(index),
+                };
+                eval_body_as_integer(self.tcx, cid, param_env).unwrap()
             }
         };
         Some(val)
diff --git a/src/librustc_mir/const_eval/pattern.rs b/src/librustc_mir/const_eval/pattern.rs
index 48438e7dbfd..a70ee2d1d64 100644
--- a/src/librustc_mir/const_eval/pattern.rs
+++ b/src/librustc_mir/const_eval/pattern.rs
@@ -12,7 +12,7 @@ use interpret::{const_val_field, const_discr};
 
 use rustc::middle::const_val::{ConstEvalErr, ErrKind, ConstVal};
 use rustc::mir::{Field, BorrowKind, Mutability};
-use rustc::mir::interpret::{Value, PrimVal};
+use rustc::mir::interpret::{GlobalId, Value, PrimVal};
 use rustc::ty::{self, TyCtxt, AdtDef, Ty, Region};
 use rustc::ty::subst::{Substs, Kind};
 use rustc::hir::{self, PatKind, RangeEnd};
@@ -673,14 +673,18 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
         let kind = match def {
             Def::Const(def_id) | Def::AssociatedConst(def_id) => {
                 let substs = self.tables.node_substs(id);
-                match self.tcx.at(span).const_eval(self.param_env.and((def_id, substs))) {
+                let instance = ty::Instance::resolve(
+                    self.tcx,
+                    self.param_env,
+                    def_id,
+                    substs,
+                ).unwrap();
+                let cid = GlobalId {
+                    instance,
+                    promoted: None,
+                };
+                match self.tcx.at(span).const_eval(self.param_env.and(cid)) {
                     Ok(value) => {
-                        let instance = ty::Instance::resolve(
-                            self.tcx,
-                            self.param_env,
-                            def_id,
-                            substs,
-                        ).unwrap();
                         return self.const_to_pat(instance, value, id, span)
                     },
                     Err(e) => {
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index e65f8f3f683..dc8bbdc60e0 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -15,6 +15,7 @@ use hair::cx::block;
 use hair::cx::to_ref::ToRef;
 use rustc::hir::def::{Def, CtorKind};
 use rustc::middle::const_val::ConstVal;
+use rustc::mir::interpret::{GlobalId, Value, PrimVal};
 use rustc::ty::{self, AdtKind, VariantDef, Ty};
 use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow, AutoBorrowMutability};
 use rustc::mir::interpret::{Value, PrimVal};
@@ -511,7 +512,17 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             let c = &cx.tcx.hir.body(count).value;
             let def_id = cx.tcx.hir.body_owner_def_id(count);
             let substs = Substs::identity_for_item(cx.tcx.global_tcx(), def_id);
-            let count = match cx.tcx.at(c.span).const_eval(cx.param_env.and((def_id, substs))) {
+            let instance = ty::Instance::resolve(
+                cx.tcx.global_tcx(),
+                cx.param_env,
+                def_id,
+                substs,
+            ).unwrap();
+            let global_id = GlobalId {
+                instance,
+                promoted: None
+            };
+            let count = match cx.tcx.at(c.span).const_eval(cx.param_env.and(global_id)) {
                 Ok(cv) => cv.val.unwrap_usize(cx.tcx),
                 Err(s) => cx.fatal_const_eval_err(&s, c.span, "expression")
             };
diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs
index 6929bccaa95..48f123b1f57 100644
--- a/src/librustc_mir/interpret/const_eval.rs
+++ b/src/librustc_mir/interpret/const_eval.rs
@@ -1,11 +1,10 @@
-use rustc::ty::{self, TyCtxt, Ty, Instance};
-use rustc::ty::layout::{self, LayoutOf};
-use rustc::ty::subst::Substs;
-use rustc::hir::def_id::DefId;
-use rustc::mir;
+use rustc::hir;
 use rustc::middle::const_val::ErrKind::{CheckMatchError, TypeckError};
 use rustc::middle::const_val::{ConstEvalErr, ConstVal};
-use const_eval::lookup_const_by_id;
+use rustc::mir;
+use rustc::ty::{self, TyCtxt, Ty, Instance};
+use rustc::ty::layout::{self, LayoutOf};
+use rustc::ty::subst::Subst;
 
 use syntax::ast::Mutability;
 use syntax::codemap::Span;
@@ -38,20 +37,18 @@ pub fn mk_eval_cx<'a, 'tcx>(
 
 pub fn eval_body<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    instance: Instance<'tcx>,
-    promoted: Option<mir::Promoted>,
+    cid: GlobalId<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
 ) -> EvalResult<'tcx, (Value, Pointer, Ty<'tcx>)> {
-    eval_body_and_ecx(tcx, instance, promoted, param_env).0
+    eval_body_and_ecx(tcx, cid, param_env).0
 }
 
 pub fn check_body<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    instance: Instance<'tcx>,
-    promoted: Option<mir::Promoted>,
+    cid: GlobalId<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
 ) {
-    let (res, ecx) = eval_body_and_ecx(tcx, instance, promoted, param_env);
+    let (res, ecx) = eval_body_and_ecx(tcx, cid, param_env);
     if let Err(mut err) = res {
         ecx.report(&mut err);
     }
@@ -59,26 +56,22 @@ pub fn check_body<'a, 'tcx>(
 
 fn eval_body_and_ecx<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    instance: Instance<'tcx>,
-    promoted: Option<mir::Promoted>,
+    cid: GlobalId<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
 ) -> (EvalResult<'tcx, (Value, Pointer, Ty<'tcx>)>, EvalContext<'a, 'tcx, CompileTimeEvaluator>) {
-    debug!("eval_body: {:?}, {:?}", instance, param_env);
+    debug!("eval_body: {:?}, {:?}", cid, param_env);
     let limits = super::ResourceLimits::default();
     let mut ecx = EvalContext::new(tcx, param_env, limits, CompileTimeEvaluator, ());
-    let cid = GlobalId {
-        instance,
-        promoted,
-    };
-
     let res = (|| {
-        if ecx.tcx.has_attr(instance.def_id(), "linkage") {
+        let mut mir = ecx.load_mir(cid.instance.def)?;
+        if let Some(index) = cid.promoted {
+            mir = &mir.promoted[index];
+        }
+        let layout = ecx.layout_of(mir.return_ty().subst(tcx, cid.instance.substs))?;
+        if ecx.tcx.has_attr(cid.instance.def_id(), "linkage") {
             return Err(ConstEvalError::NotConst("extern global".to_string()).into());
         }
-        let instance_ty = instance.ty(tcx);
         if tcx.interpret_interner.borrow().get_cached(cid).is_none() {
-            let mir = ecx.load_mir(instance.def)?;
-            let layout = ecx.layout_of(instance_ty)?;
             assert!(!layout.is_unsized());
             let ptr = ecx.memory.allocate(
                 layout.size.bytes(),
@@ -87,10 +80,10 @@ fn eval_body_and_ecx<'a, 'tcx>(
             )?;
             tcx.interpret_interner.borrow_mut().cache(cid, ptr.alloc_id);
             let cleanup = StackPopCleanup::MarkStatic(Mutability::Immutable);
-            let name = ty::tls::with(|tcx| tcx.item_path_str(instance.def_id()));
+            let name = ty::tls::with(|tcx| tcx.item_path_str(cid.instance.def_id()));
             trace!("const_eval: pushing stack frame for global: {}", name);
             ecx.push_stack_frame(
-                instance,
+                cid.instance,
                 mir.span,
                 mir,
                 Place::from_ptr(ptr, layout.align),
@@ -100,24 +93,22 @@ fn eval_body_and_ecx<'a, 'tcx>(
             while ecx.step()? {}
         }
         let alloc = tcx.interpret_interner.borrow().get_cached(cid).expect("global not cached");
-        let align = ecx.layout_of(instance_ty)?.align;
         let ptr = MemoryPointer::new(alloc, 0).into();
-        let value = match ecx.try_read_value(ptr, align, instance_ty)? {
+        let value = match ecx.try_read_value(ptr, layout.align, layout.ty)? {
             Some(val) => val,
-            _ => Value::ByRef(ptr, align),
+            _ => Value::ByRef(ptr, layout.align),
         };
-        Ok((value, ptr, instance_ty))
+        Ok((value, ptr, layout.ty))
     })();
     (res, ecx)
 }
 
 pub fn eval_body_as_integer<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    cid: GlobalId<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-    instance: Instance<'tcx>,
-    promoted: Option<mir::Promoted>,
 ) -> EvalResult<'tcx, u128> {
-    let (value, _, ty) = eval_body(tcx, instance, promoted, param_env)?;
+    let (value, _, ty) = eval_body(tcx, cid, param_env)?;
     match value {
         Value::ByVal(prim) => prim.to_bytes(),
         _ => err!(TypeNotPrimitive(ty)),
@@ -325,7 +316,7 @@ fn const_val_field_inner<'a, 'tcx>(
     field: mir::Field,
     value: Value,
     ty: Ty<'tcx>,
-) -> ::rustc::mir::interpret::EvalResult<'tcx, (Value, Ty<'tcx>)> {
+) -> EvalResult<'tcx, (Value, Ty<'tcx>)> {
     trace!("const_val_field: {:?}, {:?}, {:?}, {:?}", instance, field, value, ty);
     let mut ecx = mk_eval_cx(tcx, instance, param_env).unwrap();
     let (mut field, ty) = match value {
@@ -376,51 +367,47 @@ pub fn const_discr<'a, 'tcx>(
 
 pub fn const_eval_provider<'a, 'tcx>(
     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    key: ty::ParamEnvAnd<'tcx, (DefId, &'tcx Substs<'tcx>)>,
+    key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>,
 ) -> ::rustc::middle::const_val::EvalResult<'tcx> {
     trace!("const eval: {:?}", key);
-    let (def_id, substs) = if let Some(resolved) = lookup_const_by_id(tcx, key) {
-        resolved
-    } else {
-        return Err(ConstEvalErr {
-            span: tcx.def_span(key.value.0),
-            kind: TypeckError
-        });
-    };
+    let cid = key.value;
+    let def_id = cid.instance.def.def_id();
+    let span = tcx.def_span(def_id);
 
-    let tables = tcx.typeck_tables_of(def_id);
-    let body = if let Some(id) = tcx.hir.as_local_node_id(def_id) {
-        let body_id = tcx.hir.body_owned_by(id);
+    if let Some(id) = tcx.hir.as_local_node_id(def_id) {
+        let tables = tcx.typeck_tables_of(def_id);
 
         // Do match-check before building MIR
         if tcx.check_match(def_id).is_err() {
             return Err(ConstEvalErr {
-                span: tcx.def_span(key.value.0),
+                span,
                 kind: CheckMatchError,
             });
         }
 
-        tcx.mir_const_qualif(def_id);
-        tcx.hir.body(body_id)
-    } else {
-        tcx.extern_const_body(def_id).body
-    };
-
-    // do not continue into miri if typeck errors occurred
-    // it will fail horribly
-    if tables.tainted_by_errors {
-        return Err(ConstEvalErr { span: body.value.span, kind: TypeckError })
-    }
+        if let hir::BodyOwnerKind::Const = tcx.hir.body_owner_kind(id) {
+            tcx.mir_const_qualif(def_id);
+        }
 
+        // Do not continue into miri if typeck errors occurred; it will fail horribly
+        if tables.tainted_by_errors {
+            return Err(ConstEvalErr {
+                span,
+                kind: TypeckError
+            });
+        }
+    };
 
-    let instance = ty::Instance::new(def_id, substs);
-    match ::interpret::eval_body(tcx, instance, None, key.param_env) {
+    match ::interpret::eval_body(tcx, cid, key.param_env) {
         Ok((miri_value, _, miri_ty)) => Ok(tcx.mk_const(ty::Const {
             val: ConstVal::Value(miri_value),
             ty: miri_ty,
         })),
         Err(err) => {
-            Err(ConstEvalErr { span: body.value.span, kind: err.into() })
+            Err(ConstEvalErr {
+                span,
+                kind: err.into()
+            })
         }
     }
 }
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 26b96493310..1ad26b4cda5 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -93,6 +93,7 @@ use rustc::infer::{self, InferCtxt, InferOk, RegionVariableOrigin};
 use rustc::infer::anon_types::AnonTypeDecl;
 use rustc::infer::type_variable::{TypeVariableOrigin};
 use rustc::middle::region;
+use rustc::mir::interpret::{GlobalId};
 use rustc::ty::subst::{Kind, Subst, Substs};
 use rustc::traits::{self, FulfillmentContext, ObligationCause, ObligationCauseCode};
 use rustc::ty::{self, Ty, TyCtxt, Visibility, ToPredicate};
@@ -3999,7 +4000,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             let count_def_id = tcx.hir.body_owner_def_id(count);
             let param_env = ty::ParamEnv::empty(traits::Reveal::UserFacing);
             let substs = Substs::identity_for_item(tcx.global_tcx(), count_def_id);
-            let count = tcx.const_eval(param_env.and((count_def_id, substs)));
+            let instance = ty::Instance::resolve(
+                tcx.global_tcx(),
+                param_env,
+                count_def_id,
+                substs,
+            ).unwrap();
+            let global_id = GlobalId {
+                instance,
+                promoted: None
+            };
+            let count = tcx.const_eval(param_env.and(global_id));
 
             if let Err(ref err) = count {
                err.report(tcx, tcx.def_span(count_def_id), "constant expression");
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 595ae463ab0..0271ad269e1 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -38,7 +38,7 @@ use rustc::ty::{self, AdtKind, ToPolyTraitRef, Ty, TyCtxt};
 use rustc::ty::maps::Providers;
 use rustc::ty::util::IntTypeExt;
 use rustc::util::nodemap::{FxHashSet, FxHashMap};
-use rustc::mir::interpret::{Value, PrimVal};
+use rustc::mir::interpret::{GlobalId, Value, PrimVal};
 
 use rustc_const_math::ConstInt;
 
@@ -524,7 +524,12 @@ fn convert_enum_variant_types<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         prev_discr = Some(if let Some(e) = variant.node.disr_expr {
             let expr_did = tcx.hir.local_def_id(e.node_id);
             let substs = Substs::identity_for_item(tcx, expr_did);
-            let result = tcx.at(variant.span).const_eval(param_env.and((expr_did, substs)));
+            let instance = ty::Instance::new(expr_did, substs);
+            let global_id = GlobalId {
+                instance,
+                promoted: None
+            };
+            let result = tcx.at(variant.span).const_eval(param_env.and(global_id));
 
             // enum variant evaluation happens before the global constant check
             // so we need to report the real error