From 871513d02cf4d5c40689052aa7a1f3681fc3fdcc Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Mon, 1 Jun 2020 08:42:40 +0200
Subject: [PATCH 1/7] make miri memory TyCtxtAt a TyCtxt

---
 src/librustc_mir/interpret/eval_context.rs |  3 +--
 src/librustc_mir/interpret/memory.rs       | 20 ++++++++++----------
 2 files changed, 11 insertions(+), 12 deletions(-)

diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 6497e211de316..844f2ea07023b 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -301,7 +301,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             machine,
             tcx,
             param_env,
-            memory: Memory::new(tcx, memory_extra),
+            memory: Memory::new(*tcx, memory_extra),
             vtables: FxHashMap::default(),
         }
     }
@@ -309,7 +309,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     #[inline(always)]
     pub fn set_span(&mut self, span: Span) {
         self.tcx.span = span;
-        self.memory.tcx.span = span;
     }
 
     #[inline(always)]
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index d7f64542aa78d..61dea4d43cea6 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -14,7 +14,7 @@ use std::ptr;
 
 use rustc_ast::ast::Mutability;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_middle::ty::{self, query::TyCtxtAt, Instance, ParamEnv};
+use rustc_middle::ty::{self, TyCtxt, Instance, ParamEnv};
 use rustc_target::abi::{Align, HasDataLayout, Size, TargetDataLayout};
 
 use super::{
@@ -115,7 +115,7 @@ pub struct Memory<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
     pub extra: M::MemoryExtra,
 
     /// Lets us implement `HasDataLayout`, which is awfully convenient.
-    pub tcx: TyCtxtAt<'tcx>,
+    pub tcx: TyCtxt<'tcx>,
 }
 
 impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for Memory<'mir, 'tcx, M> {
@@ -126,7 +126,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for Memory<'mir, 'tcx, M>
 }
 
 impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
-    pub fn new(tcx: TyCtxtAt<'tcx>, extra: M::MemoryExtra) -> Self {
+    pub fn new(tcx: TyCtxt<'tcx>, extra: M::MemoryExtra) -> Self {
         Memory {
             alloc_map: M::MemoryMap::default(),
             extra_fn_ptr_map: FxHashMap::default(),
@@ -425,7 +425,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
     /// `M::tag_allocation`.
     fn get_global_alloc(
         memory_extra: &M::MemoryExtra,
-        tcx: TyCtxtAt<'tcx>,
+        tcx: TyCtxt<'tcx>,
         id: AllocId,
         is_write: bool,
     ) -> InterpResult<'tcx, Cow<'tcx, Allocation<M::PointerTag, M::AllocExtra>>> {
@@ -455,7 +455,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
                     throw_unsup!(ReadForeignStatic(def_id))
                 }
                 trace!("get_global_alloc: Need to compute {:?}", def_id);
-                let instance = Instance::mono(tcx.tcx, def_id);
+                let instance = Instance::mono(tcx, def_id);
                 let gid = GlobalId { instance, promoted: None };
                 // Use the raw query here to break validation cycles. Later uses of the static
                 // will call the full query anyway.
@@ -664,14 +664,14 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
     pub fn dump_allocs(&self, mut allocs: Vec<AllocId>) {
         // Cannot be a closure because it is generic in `Tag`, `Extra`.
         fn write_allocation_track_relocs<'tcx, Tag: Copy + fmt::Debug, Extra>(
-            tcx: TyCtxtAt<'tcx>,
+            tcx: TyCtxt<'tcx>,
             allocs_to_print: &mut VecDeque<AllocId>,
             alloc: &Allocation<Tag, Extra>,
         ) {
             for &(_, target_id) in alloc.relocations().values() {
                 allocs_to_print.push_back(target_id);
             }
-            pretty::write_allocation(tcx.tcx, alloc, &mut std::io::stderr()).unwrap();
+            pretty::write_allocation(tcx, alloc, &mut std::io::stderr()).unwrap();
         }
 
         allocs.sort();
@@ -820,7 +820,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
                 return Ok(());
             }
         };
-        let tcx = self.tcx.tcx;
+        let tcx = self.tcx;
         self.get_raw_mut(ptr.alloc_id)?.write_bytes(&tcx, ptr, src)
     }
 
@@ -846,7 +846,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
                 return Ok(());
             }
         };
-        let tcx = self.tcx.tcx;
+        let tcx = self.tcx;
         let allocation = self.get_raw_mut(ptr.alloc_id)?;
 
         for idx in 0..len {
@@ -888,7 +888,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
         let relocations =
             self.get_raw(src.alloc_id)?.prepare_relocation_copy(self, src, size, dest, length);
 
-        let tcx = self.tcx.tcx;
+        let tcx = self.tcx;
 
         // This checks relocation edges on the src.
         let src_bytes =

From dc6ffaebd5b56793f86443a0a50c06f025321198 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Mon, 1 Jun 2020 10:15:17 +0200
Subject: [PATCH 2/7] make miri InterpCx TyCtxtAt a TyCtxt, and separately
 remember the root span of the evaluation

---
 src/librustc_middle/ty/util.rs                |  1 +
 src/librustc_mir/const_eval/error.rs          |  2 +-
 src/librustc_mir/const_eval/eval_queries.rs   | 21 +++----
 src/librustc_mir/interpret/cast.rs            |  8 +--
 src/librustc_mir/interpret/eval_context.rs    | 60 ++++++++++++-------
 src/librustc_mir/interpret/intern.rs          | 18 +++---
 src/librustc_mir/interpret/intrinsics.rs      |  4 +-
 .../interpret/intrinsics/caller_location.rs   |  4 +-
 src/librustc_mir/interpret/memory.rs          |  2 +-
 src/librustc_mir/interpret/operand.rs         | 16 ++---
 src/librustc_mir/interpret/place.rs           | 39 ++++++------
 src/librustc_mir/interpret/step.rs            |  2 -
 src/librustc_mir/interpret/terminator.rs      |  8 +--
 src/librustc_mir/interpret/traits.rs          | 32 +++++-----
 src/librustc_mir/transform/const_prop.rs      | 15 ++---
 15 files changed, 123 insertions(+), 109 deletions(-)

diff --git a/src/librustc_middle/ty/util.rs b/src/librustc_middle/ty/util.rs
index c2b794ca4bdd9..29da7ff085065 100644
--- a/src/librustc_middle/ty/util.rs
+++ b/src/librustc_middle/ty/util.rs
@@ -705,6 +705,7 @@ impl<'tcx> ty::TyS<'tcx> {
     /// optimization as well as the rules around static values. Note
     /// that the `Freeze` trait is not exposed to end users and is
     /// effectively an implementation detail.
+    // FIXME: use `TyCtxtAt` instead of separate `Span`.
     pub fn is_freeze(
         &'tcx self,
         tcx: TyCtxt<'tcx>,
diff --git a/src/librustc_mir/const_eval/error.rs b/src/librustc_mir/const_eval/error.rs
index b165a69433db1..2aafafd8205d1 100644
--- a/src/librustc_mir/const_eval/error.rs
+++ b/src/librustc_mir/const_eval/error.rs
@@ -56,5 +56,5 @@ pub fn error_to_const_error<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>>(
 ) -> ConstEvalErr<'tcx> {
     error.print_backtrace();
     let stacktrace = ecx.generate_stacktrace();
-    ConstEvalErr { error: error.kind, stacktrace, span: ecx.tcx.span }
+    ConstEvalErr { error: error.kind, stacktrace, span: ecx.cur_span() }
 }
diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs
index 2c0a40b4c543c..4101ea77c9080 100644
--- a/src/librustc_mir/const_eval/eval_queries.rs
+++ b/src/librustc_mir/const_eval/eval_queries.rs
@@ -27,7 +27,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
     body: &'mir mir::Body<'tcx>,
 ) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
     debug!("eval_body_using_ecx: {:?}, {:?}", cid, ecx.param_env);
-    let tcx = ecx.tcx.tcx;
+    let tcx = ecx.tcx;
     let layout = ecx.layout_of(body.return_ty().subst(tcx, cid.instance.substs))?;
     assert!(!layout.is_unsized());
     let ret = ecx.allocate(layout, MemoryKind::Stack);
@@ -81,13 +81,14 @@ fn eval_body_using_ecx<'mir, 'tcx>(
 /// parameter. These bounds are passed to `mk_eval_cx` via the `ParamEnv` argument.
 pub(super) fn mk_eval_cx<'mir, 'tcx>(
     tcx: TyCtxt<'tcx>,
-    span: Span,
+    root_span: Span,
     param_env: ty::ParamEnv<'tcx>,
     can_access_statics: bool,
 ) -> CompileTimeEvalContext<'mir, 'tcx> {
     debug!("mk_eval_cx: {:?}", param_env);
     InterpCx::new(
-        tcx.at(span),
+        tcx,
+        root_span,
         param_env,
         CompileTimeInterpreter::new(tcx.sess.const_eval_limit()),
         MemoryExtra { can_access_statics },
@@ -163,7 +164,7 @@ pub(super) fn op_to_const<'tcx>(
                         0,
                     ),
                 };
-                let len = b.to_machine_usize(&ecx.tcx.tcx).unwrap();
+                let len = b.to_machine_usize(ecx).unwrap();
                 let start = start.try_into().unwrap();
                 let len: usize = len.try_into().unwrap();
                 ConstValue::Slice { data, start, end: start + len }
@@ -213,7 +214,7 @@ fn validate_and_turn_into_const<'tcx>(
 
     val.map_err(|error| {
         let err = error_to_const_error(&ecx, error);
-        err.struct_error(ecx.tcx, "it is undefined behavior to use this value", |mut diag| {
+        err.struct_error(ecx.tcx_at(), "it is undefined behavior to use this value", |mut diag| {
             diag.note(note_on_undefined_behavior_error());
             diag.emit();
         })
@@ -299,9 +300,9 @@ pub fn const_eval_raw_provider<'tcx>(
 
     let is_static = tcx.is_static(def_id);
 
-    let span = tcx.def_span(cid.instance.def_id());
     let mut ecx = InterpCx::new(
-        tcx.at(span),
+        tcx,
+        tcx.def_span(cid.instance.def_id()),
         key.param_env,
         CompileTimeInterpreter::new(tcx.sess.const_eval_limit()),
         MemoryExtra { can_access_statics: is_static },
@@ -316,7 +317,7 @@ pub fn const_eval_raw_provider<'tcx>(
             if is_static {
                 // Ensure that if the above error was either `TooGeneric` or `Reported`
                 // an error must be reported.
-                let v = err.report_as_error(ecx.tcx, "could not evaluate static initializer");
+                let v = err.report_as_error(ecx.tcx_at(), "could not evaluate static initializer");
 
                 // If this is `Reveal:All`, then we need to make sure an error is reported but if
                 // this is `Reveal::UserFacing`, then it's expected that we could get a
@@ -372,13 +373,13 @@ pub fn const_eval_raw_provider<'tcx>(
                         // anything else (array lengths, enum initializers, constant patterns) are
                         // reported as hard errors
                         } else {
-                            err.report_as_error(ecx.tcx, "evaluation of constant value failed")
+                            err.report_as_error(ecx.tcx_at(), "evaluation of constant value failed")
                         }
                     }
                 }
             } else {
                 // use of broken constant from other crate
-                err.report_as_error(ecx.tcx, "could not evaluate constant")
+                err.report_as_error(ecx.tcx_at(), "could not evaluate constant")
             }
         })
 }
diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs
index 0fd695586eb98..287b43ac50f96 100644
--- a/src/librustc_mir/interpret/cast.rs
+++ b/src/librustc_mir/interpret/cast.rs
@@ -56,7 +56,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                         }
 
                         let instance = ty::Instance::resolve_for_fn_ptr(
-                            *self.tcx,
+                            self.tcx,
                             self.param_env,
                             def_id,
                             substs,
@@ -91,7 +91,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                         }
 
                         let instance = ty::Instance::resolve_closure(
-                            *self.tcx,
+                            self.tcx,
                             def_id,
                             substs,
                             ty::ClosureKind::FnOnce,
@@ -140,7 +140,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // Handle cast from a univariant (ZST) enum.
         match src.layout.variants {
             Variants::Single { index } => {
-                if let Some(discr) = src.layout.ty.discriminant_for_variant(*self.tcx, index) {
+                if let Some(discr) = src.layout.ty.discriminant_for_variant(self.tcx, index) {
                     assert!(src.layout.is_zst());
                     let discr_layout = self.layout_of(discr.ty)?;
                     return Ok(self.cast_from_scalar(discr.val, discr_layout, cast_ty).into());
@@ -270,7 +270,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 // u64 cast is from usize to u64, which is always good
                 let val = Immediate::new_slice(
                     ptr,
-                    length.eval_usize(self.tcx.tcx, self.param_env),
+                    length.eval_usize(self.tcx, self.param_env),
                     self,
                 );
                 self.write_immediate(val, dest)
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 844f2ea07023b..1715b6fede962 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -33,7 +33,11 @@ pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
     pub machine: M,
 
     /// The results of the type checker, from rustc.
-    pub tcx: TyCtxtAt<'tcx>,
+    pub tcx: TyCtxt<'tcx>,
+
+    /// The span of the "root" of the evaluation, i.e., the const
+    /// we are evaluating (if this is CTFE).
+    pub(super) root_span: Span,
 
     /// Bounds in scope for polymorphic evaluations.
     pub(crate) param_env: ty::ParamEnv<'tcx>,
@@ -196,7 +200,7 @@ where
 {
     #[inline]
     fn tcx(&self) -> TyCtxt<'tcx> {
-        *self.tcx
+        self.tcx
     }
 }
 
@@ -209,13 +213,13 @@ where
     }
 }
 
-impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> LayoutOf for InterpCx<'mir, 'tcx, M> {
+impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> LayoutOf for InterpCx<'mir, 'tcx, M> {
     type Ty = Ty<'tcx>;
     type TyAndLayout = InterpResult<'tcx, TyAndLayout<'tcx>>;
 
     #[inline]
     fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout {
-        self.tcx
+        self.tcx_at()
             .layout_of(self.param_env.and(ty))
             .map_err(|layout| err_inval!(Layout(layout)).into())
     }
@@ -292,7 +296,8 @@ pub(super) fn from_known_layout<'tcx>(
 
 impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     pub fn new(
-        tcx: TyCtxtAt<'tcx>,
+        tcx: TyCtxt<'tcx>,
+        root_span: Span,
         param_env: ty::ParamEnv<'tcx>,
         machine: M,
         memory_extra: M::MemoryExtra,
@@ -300,15 +305,26 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         InterpCx {
             machine,
             tcx,
+            root_span,
             param_env,
-            memory: Memory::new(*tcx, memory_extra),
+            memory: Memory::new(tcx, memory_extra),
             vtables: FxHashMap::default(),
         }
     }
 
     #[inline(always)]
-    pub fn set_span(&mut self, span: Span) {
-        self.tcx.span = span;
+    pub fn cur_span(&self) -> Span {
+        self
+            .stack()
+            .last()
+            .and_then(|f| f.current_source_info())
+            .map(|si| si.span)
+            .unwrap_or(self.root_span)
+    }
+
+    #[inline(always)]
+    pub fn tcx_at(&self) -> TyCtxtAt<'tcx> {
+        self.tcx.at(self.cur_span())
     }
 
     #[inline(always)]
@@ -386,12 +402,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
     #[inline]
     pub fn type_is_sized(&self, ty: Ty<'tcx>) -> bool {
-        ty.is_sized(self.tcx, self.param_env)
+        ty.is_sized(self.tcx_at(), self.param_env)
     }
 
     #[inline]
     pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
-        ty.is_freeze(*self.tcx, self.param_env, DUMMY_SP)
+        ty.is_freeze(self.tcx, self.param_env, self.cur_span())
     }
 
     pub fn load_mir(
@@ -402,20 +418,20 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // do not continue if typeck errors occurred (can only occur in local crate)
         let did = instance.def_id();
         if let Some(did) = did.as_local() {
-            if self.tcx.has_typeck_tables(did) {
-                if let Some(error_reported) = self.tcx.typeck_tables_of(did).tainted_by_errors {
+            if self.tcx_at().has_typeck_tables(did) {
+                if let Some(error_reported) = self.tcx_at().typeck_tables_of(did).tainted_by_errors {
                     throw_inval!(TypeckError(error_reported))
                 }
             }
         }
         trace!("load mir(instance={:?}, promoted={:?})", instance, promoted);
         if let Some(promoted) = promoted {
-            return Ok(&self.tcx.promoted_mir(did)[promoted]);
+            return Ok(&self.tcx_at().promoted_mir(did)[promoted]);
         }
         match instance {
             ty::InstanceDef::Item(def_id) => {
-                if self.tcx.is_mir_available(did) {
-                    Ok(self.tcx.optimized_mir(did))
+                if self.tcx_at().is_mir_available(did) {
+                    Ok(self.tcx_at().optimized_mir(did))
                 } else {
                     throw_unsup!(NoMirFor(def_id))
                 }
@@ -456,7 +472,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         trace!("resolve: {:?}, {:#?}", def_id, substs);
         trace!("param_env: {:#?}", self.param_env);
         trace!("substs: {:#?}", substs);
-        match ty::Instance::resolve(*self.tcx, self.param_env, def_id, substs) {
+        match ty::Instance::resolve(self.tcx, self.param_env, def_id, substs) {
             Ok(Some(instance)) => Ok(instance),
             Ok(None) => throw_inval!(TooGeneric),
 
@@ -475,7 +491,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // have to support that case (mostly by skipping all caching).
         match frame.locals.get(local).and_then(|state| state.layout.get()) {
             None => {
-                let layout = from_known_layout(self.tcx, layout, || {
+                let layout = from_known_layout(self.tcx_at(), layout, || {
                     let local_ty = frame.body.local_decls[local].ty;
                     let local_ty =
                         self.subst_from_frame_and_normalize_erasing_regions(frame, local_ty);
@@ -560,7 +576,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let size = size.align_to(align);
 
                 // Check if this brought us over the size limit.
-                if size.bytes() >= self.tcx.data_layout().obj_size_bound() {
+                if size.bytes() >= self.tcx.data_layout.obj_size_bound() {
                     throw_ub!(InvalidMeta("total size is bigger than largest supported object"));
                 }
                 Ok(Some((size, align)))
@@ -576,7 +592,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let elem = layout.field(self, 0)?;
 
                 // Make sure the slice is not too big.
-                let size = elem.size.checked_mul(len, &*self.tcx).ok_or_else(|| {
+                let size = elem.size.checked_mul(len, self).ok_or_else(|| {
                     err_ub!(InvalidMeta("slice is bigger than largest supported object"))
                 })?;
                 Ok(Some((size, elem.align.abi)))
@@ -627,7 +643,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         let mut locals = IndexVec::from_elem(dummy, &body.local_decls);
 
         // Now mark those locals as dead that we do not want to initialize
-        match self.tcx.def_kind(instance.def_id()) {
+        match self.tcx_at().def_kind(instance.def_id()) {
             // statics and constants don't have `Storage*` statements, no need to look for them
             //
             // FIXME: The above is likely untrue. See
@@ -842,7 +858,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         } else {
             self.param_env
         };
-        let val = self.tcx.const_eval_global_id(param_env, gid, Some(self.tcx.span))?;
+        let val = self.tcx.const_eval_global_id(param_env, gid, Some(self.cur_span()))?;
 
         // Even though `ecx.const_eval` is called from `eval_const_to_op` we can never have a
         // recursion deeper than one level, because the `tcx.const_eval` above is guaranteed to not
@@ -873,7 +889,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // FIXME: We can hit delay_span_bug if this is an invalid const, interning finds
         // that problem, but we never run validation to show an error. Can we ensure
         // this does not happen?
-        let val = self.tcx.const_eval_raw(param_env.and(gid))?;
+        let val = self.tcx_at().const_eval_raw(param_env.and(gid))?;
         self.raw_const_to_mplace(val)
     }
 
diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs
index 02a7f24a1e351..284a1d5ea61ef 100644
--- a/src/librustc_mir/interpret/intern.rs
+++ b/src/librustc_mir/interpret/intern.rs
@@ -93,7 +93,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>(
             // in the value the dangling reference lies.
             // The `delay_span_bug` ensures that we don't forget such a check in validation.
             if tcx.get_global_alloc(alloc_id).is_none() {
-                tcx.sess.delay_span_bug(ecx.tcx.span, "tried to intern dangling pointer");
+                tcx.sess.delay_span_bug(ecx.root_span, "tried to intern dangling pointer");
             }
             // treat dangling pointers like other statics
             // just to stop trying to recurse into them
@@ -111,7 +111,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>(
     if let InternMode::Static(mutability) = mode {
         // For this, we need to take into account `UnsafeCell`. When `ty` is `None`, we assume
         // no interior mutability.
-        let frozen = ty.map_or(true, |ty| ty.is_freeze(ecx.tcx.tcx, ecx.param_env, ecx.tcx.span));
+        let frozen = ty.map_or(true, |ty| ty.is_freeze(ecx.tcx, ecx.param_env, ecx.root_span));
         // For statics, allocation mutability is the combination of the place mutability and
         // the type mutability.
         // The entire allocation needs to be mutable if it contains an `UnsafeCell` anywhere.
@@ -174,7 +174,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir
                     // they caused.  It also helps us to find cases where const-checking
                     // failed to prevent an `UnsafeCell` (but as `ignore_interior_mut_in_const`
                     // shows that part is not airtight).
-                    mutable_memory_in_const(self.ecx.tcx, "`UnsafeCell`");
+                    mutable_memory_in_const(self.ecx.tcx_at(), "`UnsafeCell`");
                 }
                 // We are crossing over an `UnsafeCell`, we can mutate again. This means that
                 // References we encounter inside here are interned as pointing to mutable
@@ -192,7 +192,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir
     fn visit_value(&mut self, mplace: MPlaceTy<'tcx>) -> InterpResult<'tcx> {
         // Handle Reference types, as these are the only relocations supported by const eval.
         // Raw pointers (and boxes) are handled by the `leftover_relocations` logic.
-        let tcx = self.ecx.tcx;
+        let tcx = self.ecx.tcx.at(self.ecx.root_span);
         let ty = mplace.layout.ty;
         if let ty::Ref(_, referenced_ty, ref_mutability) = ty.kind {
             let value = self.ecx.read_immediate(mplace.into())?;
@@ -254,7 +254,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir
                         if ref_mutability == Mutability::Mut {
                             match referenced_ty.kind {
                                 ty::Array(_, n)
-                                    if n.eval_usize(tcx.tcx, self.ecx.param_env) == 0 => {}
+                                    if n.eval_usize(self.ecx.tcx, self.ecx.param_env) == 0 => {}
                                 ty::Slice(_)
                                     if mplace.meta.unwrap_meta().to_machine_usize(self.ecx)?
                                         == 0 => {}
@@ -358,7 +358,7 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
             Ok(()) => {}
             Err(error) => {
                 ecx.tcx.sess.delay_span_bug(
-                    ecx.tcx.span,
+                    ecx.root_span,
                     "error during interning should later cause validation failure",
                 );
                 // Some errors shouldn't come up because creating them causes
@@ -407,7 +407,7 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
                     // such as `const CONST_RAW: *const Vec<i32> = &Vec::new() as *const _;`.
                     ecx.tcx
                         .sess
-                        .span_err(ecx.tcx.span, "untyped pointers are not allowed in constant");
+                        .span_err(ecx.root_span, "untyped pointers are not allowed in constant");
                     // For better errors later, mark the allocation as immutable.
                     alloc.mutability = Mutability::Not;
                 }
@@ -422,11 +422,11 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
         } else if ecx.memory.dead_alloc_map.contains_key(&alloc_id) {
             // Codegen does not like dangling pointers, and generally `tcx` assumes that
             // all allocations referenced anywhere actually exist. So, make sure we error here.
-            ecx.tcx.sess.span_err(ecx.tcx.span, "encountered dangling pointer in final constant");
+            ecx.tcx.sess.span_err(ecx.root_span, "encountered dangling pointer in final constant");
         } else if ecx.tcx.get_global_alloc(alloc_id).is_none() {
             // We have hit an `AllocId` that is neither in local or global memory and isn't
             // marked as dangling by local memory.  That should be impossible.
-            span_bug!(ecx.tcx.span, "encountered unknown alloc id {:?}", alloc_id);
+            span_bug!(ecx.root_span, "encountered unknown alloc id {:?}", alloc_id);
         }
     }
 }
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index 115a472cabe5e..c62fd316dc584 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -347,7 +347,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let index = u64::from(self.read_scalar(args[1])?.to_u32()?);
                 let elem = args[2];
                 let input = args[0];
-                let (len, e_ty) = input.layout.ty.simd_size_and_type(self.tcx.tcx);
+                let (len, e_ty) = input.layout.ty.simd_size_and_type(self.tcx);
                 assert!(
                     index < len,
                     "Index `{}` must be in bounds of vector type `{}`: `[0, {})`",
@@ -374,7 +374,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             }
             sym::simd_extract => {
                 let index = u64::from(self.read_scalar(args[1])?.to_u32()?);
-                let (len, e_ty) = args[0].layout.ty.simd_size_and_type(self.tcx.tcx);
+                let (len, e_ty) = args[0].layout.ty.simd_size_and_type(self.tcx);
                 assert!(
                     index < len,
                     "index `{}` is out-of-bounds of vector type `{}` with length `{}`",
diff --git a/src/librustc_mir/interpret/intrinsics/caller_location.rs b/src/librustc_mir/interpret/intrinsics/caller_location.rs
index ddeed92f85124..193d38dc5523e 100644
--- a/src/librustc_mir/interpret/intrinsics/caller_location.rs
+++ b/src/librustc_mir/interpret/intrinsics/caller_location.rs
@@ -25,7 +25,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     "find_closest_untracked_caller_location: checking frame {:?}",
                     frame.instance
                 );
-                !frame.instance.def.requires_caller_location(*self.tcx)
+                !frame.instance.def.requires_caller_location(self.tcx)
             })
             // Assert that there is always such a frame.
             .unwrap();
@@ -58,7 +58,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         let loc_ty = self
             .tcx
             .type_of(self.tcx.require_lang_item(PanicLocationLangItem, None))
-            .subst(*self.tcx, self.tcx.mk_substs([self.tcx.lifetimes.re_erased.into()].iter()));
+            .subst(self.tcx, self.tcx.mk_substs([self.tcx.lifetimes.re_erased.into()].iter()));
         let loc_layout = self.layout_of(loc_ty).unwrap();
         let location = self.allocate(loc_layout, MemoryKind::CallerLocation);
 
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index 61dea4d43cea6..8af1a8ac608ac 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -14,7 +14,7 @@ use std::ptr;
 
 use rustc_ast::ast::Mutability;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_middle::ty::{self, TyCtxt, Instance, ParamEnv};
+use rustc_middle::ty::{self, Instance, ParamEnv, TyCtxt};
 use rustc_target::abi::{Align, HasDataLayout, Size, TargetDataLayout};
 
 use super::{
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index db4473154c471..c9250098fedba 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -471,9 +471,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         trace!("eval_place_to_op: got {:?}", *op);
         // Sanity-check the type we ended up with.
         debug_assert!(mir_assign_valid_types(
-            *self.tcx,
+            self.tcx,
             self.layout_of(self.subst_from_current_frame_and_normalize_erasing_regions(
-                place.ty(&self.frame().body.local_decls, *self.tcx).ty
+                place.ty(&self.frame().body.local_decls, self.tcx).ty
             ))?,
             op.layout,
         ));
@@ -554,7 +554,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // documentation).
         let val_val = M::adjust_global_const(self, val_val)?;
         // Other cases need layout.
-        let layout = from_known_layout(self.tcx, layout, || self.layout_of(val.ty))?;
+        let layout = from_known_layout(self.tcx_at(), layout, || self.layout_of(val.ty))?;
         let op = match val_val {
             ConstValue::ByRef { alloc, offset } => {
                 let id = self.tcx.create_memory_alloc(alloc);
@@ -589,7 +589,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         trace!("read_discriminant_value {:#?}", op.layout);
 
         // Get type and layout of the discriminant.
-        let discr_layout = self.layout_of(op.layout.ty.discriminant_ty(*self.tcx))?;
+        let discr_layout = self.layout_of(op.layout.ty.discriminant_ty(self.tcx))?;
         trace!("discriminant type: {:?}", discr_layout.ty);
 
         // We use "discriminant" to refer to the value associated with a particular enum variant.
@@ -601,7 +601,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // rather confusing.
         let (tag_scalar_layout, tag_kind, tag_index) = match op.layout.variants {
             Variants::Single { index } => {
-                let discr = match op.layout.ty.discriminant_for_variant(*self.tcx, index) {
+                let discr = match op.layout.ty.discriminant_for_variant(self.tcx, index) {
                     Some(discr) => {
                         // This type actually has discriminants.
                         assert_eq!(discr.ty, discr_layout.ty);
@@ -630,7 +630,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         //   may be a pointer. This is `tag_val.layout`; we just use it for sanity checks.
 
         // Get layout for tag.
-        let tag_layout = self.layout_of(tag_scalar_layout.value.to_int_ty(*self.tcx))?;
+        let tag_layout = self.layout_of(tag_scalar_layout.value.to_int_ty(self.tcx))?;
 
         // Read tag and sanity-check `tag_layout`.
         let tag_val = self.read_immediate(self.operand_field(op, tag_index)?)?;
@@ -651,12 +651,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 // Convert discriminant to variant index, and catch invalid discriminants.
                 let index = match op.layout.ty.kind {
                     ty::Adt(adt, _) => {
-                        adt.discriminants(self.tcx.tcx).find(|(_, var)| var.val == discr_bits)
+                        adt.discriminants(self.tcx).find(|(_, var)| var.val == discr_bits)
                     }
                     ty::Generator(def_id, substs, _) => {
                         let substs = substs.as_generator();
                         substs
-                            .discriminants(def_id, self.tcx.tcx)
+                            .discriminants(def_id, self.tcx)
                             .find(|(_, var)| var.val == discr_bits)
                     }
                     _ => bug!("tagged layout for non-adt non-generator"),
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index 3f0800b12b549..0b4e92574a066 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -404,7 +404,7 @@ where
                     // to get some code to work that probably ought to work.
                     field_layout.align.abi
                 }
-                None => bug!("Cannot compute offset for extern type field at non-0 offset"),
+                None => span_bug!(self.cur_span(), "cannot compute offset for extern type field at non-0 offset"),
             };
             (base.meta, offset.align_to(align))
         } else {
@@ -440,7 +440,7 @@ where
                 assert!(!field_layout.is_unsized());
                 base.offset(offset, MemPlaceMeta::None, field_layout, self)
             }
-            _ => bug!("`mplace_index` called on non-array type {:?}", base.layout.ty),
+            _ => span_bug!(self.cur_span(), "`mplace_index` called on non-array type {:?}", base.layout.ty),
         }
     }
 
@@ -454,7 +454,7 @@ where
         let len = base.len(self)?; // also asserts that we have a type where this makes sense
         let stride = match base.layout.fields {
             FieldsShape::Array { stride, .. } => stride,
-            _ => bug!("mplace_array_fields: expected an array layout"),
+            _ => span_bug!(self.cur_span(), "mplace_array_fields: expected an array layout"),
         };
         let layout = base.layout.field(self, 0)?;
         let dl = &self.tcx.data_layout;
@@ -484,7 +484,7 @@ where
         // (that have count 0 in their layout).
         let from_offset = match base.layout.fields {
             FieldsShape::Array { stride, .. } => stride * from, // `Size` multiplication is checked
-            _ => bug!("Unexpected layout of index access: {:#?}", base.layout),
+            _ => span_bug!(self.cur_span(), "unexpected layout of index access: {:#?}", base.layout),
         };
 
         // Compute meta and new layout
@@ -497,7 +497,7 @@ where
                 let len = Scalar::from_machine_usize(inner_len, self);
                 (MemPlaceMeta::Meta(len), base.layout.ty)
             }
-            _ => bug!("cannot subslice non-array type: `{:?}`", base.layout.ty),
+            _ => span_bug!(self.cur_span(), "cannot subslice non-array type: `{:?}`", base.layout.ty),
         };
         let layout = self.layout_of(ty)?;
         base.offset(from_offset, meta, layout, self)
@@ -640,9 +640,9 @@ where
         self.dump_place(place_ty.place);
         // Sanity-check the type we ended up with.
         debug_assert!(mir_assign_valid_types(
-            *self.tcx,
+            self.tcx,
             self.layout_of(self.subst_from_current_frame_and_normalize_erasing_regions(
-                place.ty(&self.frame().body.local_decls, *self.tcx).ty
+                place.ty(&self.frame().body.local_decls, self.tcx).ty
             ))?,
             place_ty.layout,
         ));
@@ -768,7 +768,7 @@ where
             None => return Ok(()), // zero-sized access
         };
 
-        let tcx = &*self.tcx;
+        let tcx = self.tcx;
         // FIXME: We should check that there are dest.layout.size many bytes available in
         // memory.  The code below is not sufficient, with enough padding it might not
         // cover all the bytes!
@@ -777,11 +777,11 @@ where
                 match dest.layout.abi {
                     Abi::Scalar(_) => {} // fine
                     _ => {
-                        bug!("write_immediate_to_mplace: invalid Scalar layout: {:#?}", dest.layout)
+                        span_bug!(self.cur_span(), "write_immediate_to_mplace: invalid Scalar layout: {:#?}", dest.layout)
                     }
                 }
                 self.memory.get_raw_mut(ptr.alloc_id)?.write_scalar(
-                    tcx,
+                    &tcx,
                     ptr,
                     scalar,
                     dest.layout.size,
@@ -793,7 +793,8 @@ where
                 // which `ptr.offset(b_offset)` cannot possibly fail to satisfy.
                 let (a, b) = match dest.layout.abi {
                     Abi::ScalarPair(ref a, ref b) => (&a.value, &b.value),
-                    _ => bug!(
+                    _ => span_bug!(
+                        self.cur_span(),
                         "write_immediate_to_mplace: invalid ScalarPair layout: {:#?}",
                         dest.layout
                     ),
@@ -806,8 +807,8 @@ where
                 // but that does not work: We could be a newtype around a pair, then the
                 // fields do not match the `ScalarPair` components.
 
-                self.memory.get_raw_mut(ptr.alloc_id)?.write_scalar(tcx, ptr, a_val, a_size)?;
-                self.memory.get_raw_mut(b_ptr.alloc_id)?.write_scalar(tcx, b_ptr, b_val, b_size)
+                self.memory.get_raw_mut(ptr.alloc_id)?.write_scalar(&tcx, ptr, a_val, a_size)?;
+                self.memory.get_raw_mut(b_ptr.alloc_id)?.write_scalar(&tcx, b_ptr, b_val, b_size)
             }
         }
     }
@@ -841,9 +842,9 @@ where
     ) -> InterpResult<'tcx> {
         // We do NOT compare the types for equality, because well-typed code can
         // actually "transmute" `&mut T` to `&T` in an assignment without a cast.
-        if !mir_assign_valid_types(self.tcx.tcx, src.layout, dest.layout) {
+        if !mir_assign_valid_types(self.tcx, src.layout, dest.layout) {
             span_bug!(
-                self.tcx.span,
+                self.cur_span(),
                 "type mismatch when copying!\nsrc: {:?},\ndest: {:?}",
                 src.layout.ty,
                 dest.layout.ty,
@@ -898,7 +899,7 @@ where
         src: OpTy<'tcx, M::PointerTag>,
         dest: PlaceTy<'tcx, M::PointerTag>,
     ) -> InterpResult<'tcx> {
-        if mir_assign_valid_types(self.tcx.tcx, src.layout, dest.layout) {
+        if mir_assign_valid_types(self.tcx, src.layout, dest.layout) {
             // Fast path: Just use normal `copy_op`
             return self.copy_op(src, dest);
         }
@@ -910,7 +911,7 @@ where
             // on `typeck_tables().has_errors` at all const eval entry points.
             debug!("Size mismatch when transmuting!\nsrc: {:#?}\ndest: {:#?}", src, dest);
             self.tcx.sess.delay_span_bug(
-                self.tcx.span,
+                self.cur_span(),
                 "size-changing transmute, should have been caught by transmute checking",
             );
             throw_inval!(TransmuteSizeDiff(src.layout.ty, dest.layout.ty));
@@ -1056,7 +1057,7 @@ where
                 // `TyAndLayout::for_variant()` call earlier already checks the variant is valid.
 
                 let discr_val =
-                    dest.layout.ty.discriminant_for_variant(*self.tcx, variant_index).unwrap().val;
+                    dest.layout.ty.discriminant_for_variant(self.tcx, variant_index).unwrap().val;
 
                 // raw discriminants for enums are isize or bigger during
                 // their computation, but the in-memory tag is the smallest possible
@@ -1085,7 +1086,7 @@ where
                         .expect("overflow computing relative variant idx");
                     // We need to use machine arithmetic when taking into account `niche_start`:
                     // discr_val = variant_index_relative + niche_start_val
-                    let discr_layout = self.layout_of(discr_layout.value.to_int_ty(*self.tcx))?;
+                    let discr_layout = self.layout_of(discr_layout.value.to_int_ty(self.tcx))?;
                     let niche_start_val = ImmTy::from_uint(niche_start, discr_layout);
                     let variant_index_relative_val =
                         ImmTy::from_uint(variant_index_relative, discr_layout);
diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs
index 02a709ab1a134..16c6396799e63 100644
--- a/src/librustc_mir/interpret/step.rs
+++ b/src/librustc_mir/interpret/step.rs
@@ -76,7 +76,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
     fn statement(&mut self, stmt: &mir::Statement<'tcx>) -> InterpResult<'tcx> {
         info!("{:?}", stmt);
-        self.set_span(stmt.source_info.span);
 
         use rustc_middle::mir::StatementKind::*;
 
@@ -279,7 +278,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
     fn terminator(&mut self, terminator: &mir::Terminator<'tcx>) -> InterpResult<'tcx> {
         info!("{:?}", terminator.kind);
-        self.set_span(terminator.source_info.span);
 
         self.eval_terminator(terminator)?;
         if !self.stack().is_empty() {
diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs
index cd7621ea9752b..9a4dd0a5204f9 100644
--- a/src/librustc_mir/interpret/terminator.rs
+++ b/src/librustc_mir/interpret/terminator.rs
@@ -69,7 +69,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                         (fn_val, caller_abi)
                     }
                     ty::FnDef(def_id, substs) => {
-                        let sig = func.layout.ty.fn_sig(*self.tcx);
+                        let sig = func.layout.ty.fn_sig(self.tcx);
                         (FnVal::Instance(self.resolve(def_id, substs)?), sig.abi())
                     }
                     _ => span_bug!(
@@ -96,7 +96,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let ty = place.layout.ty;
                 trace!("TerminatorKind::drop: {:?}, type {}", location, ty);
 
-                let instance = Instance::resolve_drop_in_place(*self.tcx, ty);
+                let instance = Instance::resolve_drop_in_place(self.tcx, ty);
                 self.drop_in_place(place, instance, target, unwind)?;
             }
 
@@ -227,9 +227,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // ABI check
         {
             let callee_abi = {
-                let instance_ty = instance.ty_env(*self.tcx, self.param_env);
+                let instance_ty = instance.ty_env(self.tcx, self.param_env);
                 match instance_ty.kind {
-                    ty::FnDef(..) => instance_ty.fn_sig(*self.tcx).abi(),
+                    ty::FnDef(..) => instance_ty.fn_sig(self.tcx).abi(),
                     ty::Closure(..) => Abi::RustCall,
                     ty::Generator(..) => Abi::Rust,
                     _ => bug!("unexpected callee ty: {:?}", instance_ty),
diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs
index b9f9d37df7645..87493a8d383ec 100644
--- a/src/librustc_mir/interpret/traits.rs
+++ b/src/librustc_mir/interpret/traits.rs
@@ -2,7 +2,7 @@ use std::convert::TryFrom;
 
 use rustc_middle::mir::interpret::{InterpResult, Pointer, PointerArithmetic, Scalar};
 use rustc_middle::ty::{self, Instance, Ty, TypeFoldable};
-use rustc_target::abi::{Align, HasDataLayout, LayoutOf, Size};
+use rustc_target::abi::{Align, LayoutOf, Size};
 
 use super::{FnVal, InterpCx, Machine, MemoryKind};
 
@@ -36,10 +36,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         }
 
         let methods = if let Some(poly_trait_ref) = poly_trait_ref {
-            let trait_ref = poly_trait_ref.with_self_ty(*self.tcx, ty);
+            let trait_ref = poly_trait_ref.with_self_ty(self.tcx, ty);
             let trait_ref = self.tcx.erase_regions(&trait_ref);
 
-            self.tcx.vtable_methods(trait_ref)
+            self.tcx_at().vtable_methods(trait_ref)
         } else {
             &[]
         };
@@ -49,8 +49,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         let size = layout.size.bytes();
         let align = layout.align.abi.bytes();
 
+        let tcx = self.tcx;
         let ptr_size = self.pointer_size();
-        let ptr_align = self.tcx.data_layout.pointer_align.abi;
+        let ptr_align = tcx.data_layout.pointer_align.abi;
         // /////////////////////////////////////////////////////////////////////////////////////////
         // If you touch this code, be sure to also make the corresponding changes to
         // `get_vtable` in `rust_codegen_llvm/meth.rs`.
@@ -60,33 +61,32 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             ptr_align,
             MemoryKind::Vtable,
         );
-        let tcx = &*self.tcx;
 
-        let drop = Instance::resolve_drop_in_place(*tcx, ty);
+        let drop = Instance::resolve_drop_in_place(tcx, ty);
         let drop = self.memory.create_fn_alloc(FnVal::Instance(drop));
 
         // No need to do any alignment checks on the memory accesses below, because we know the
         // allocation is correctly aligned as we created it above. Also we're only offsetting by
         // multiples of `ptr_align`, which means that it will stay aligned to `ptr_align`.
         let vtable_alloc = self.memory.get_raw_mut(vtable.alloc_id)?;
-        vtable_alloc.write_ptr_sized(tcx, vtable, drop.into())?;
+        vtable_alloc.write_ptr_sized(&tcx, vtable, drop.into())?;
 
-        let size_ptr = vtable.offset(ptr_size, tcx)?;
-        vtable_alloc.write_ptr_sized(tcx, size_ptr, Scalar::from_uint(size, ptr_size).into())?;
-        let align_ptr = vtable.offset(ptr_size * 2, tcx)?;
-        vtable_alloc.write_ptr_sized(tcx, align_ptr, Scalar::from_uint(align, ptr_size).into())?;
+        let size_ptr = vtable.offset(ptr_size, &tcx)?;
+        vtable_alloc.write_ptr_sized(&tcx, size_ptr, Scalar::from_uint(size, ptr_size).into())?;
+        let align_ptr = vtable.offset(ptr_size * 2, &tcx)?;
+        vtable_alloc.write_ptr_sized(&tcx, align_ptr, Scalar::from_uint(align, ptr_size).into())?;
 
         for (i, method) in methods.iter().enumerate() {
             if let Some((def_id, substs)) = *method {
                 // resolve for vtable: insert shims where needed
                 let instance =
-                    ty::Instance::resolve_for_vtable(*tcx, self.param_env, def_id, substs)
+                    ty::Instance::resolve_for_vtable(tcx, self.param_env, def_id, substs)
                         .ok_or_else(|| err_inval!(TooGeneric))?;
                 let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance));
                 // We cannot use `vtable_allic` as we are creating fn ptrs in this loop.
-                let method_ptr = vtable.offset(ptr_size * (3 + i as u64), tcx)?;
+                let method_ptr = vtable.offset(ptr_size * (3 + i as u64), &tcx)?;
                 self.memory.get_raw_mut(vtable.alloc_id)?.write_ptr_sized(
-                    tcx,
+                    &tcx,
                     method_ptr,
                     fn_ptr.into(),
                 )?;
@@ -142,7 +142,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // to determine the type.
         let drop_instance = self.memory.get_fn(drop_fn)?.as_instance()?;
         trace!("Found drop fn: {:?}", drop_instance);
-        let fn_sig = drop_instance.ty_env(*self.tcx, self.param_env).fn_sig(*self.tcx);
+        let fn_sig = drop_instance.ty_env(self.tcx, self.param_env).fn_sig(self.tcx);
         let fn_sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, &fn_sig);
         // The drop function takes `*mut T` where `T` is the type being dropped, so get that.
         let args = fn_sig.inputs();
@@ -171,7 +171,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             alloc.read_ptr_sized(self, vtable.offset(pointer_size * 2, self)?)?.not_undef()?;
         let align = u64::try_from(self.force_bits(align, pointer_size)?).unwrap();
 
-        if size >= self.tcx.data_layout().obj_size_bound() {
+        if size >= self.tcx.data_layout.obj_size_bound() {
             throw_ub_format!(
                 "invalid vtable: \
                 size is bigger than largest supported object"
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 0ff60cbd55d3c..133c05fc2f92b 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -313,7 +313,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         let param_env = tcx.param_env(def_id).with_reveal_all();
 
         let span = tcx.def_span(def_id);
-        let mut ecx = InterpCx::new(tcx.at(span), param_env, ConstPropMachine::new(), ());
+        let mut ecx = InterpCx::new(tcx, span, param_env, ConstPropMachine::new(), ());
         let can_const_prop = CanConstProp::check(body);
 
         let ret = ecx
@@ -404,8 +404,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         match self.ecx.eval_const_to_op(c.literal, None) {
             Ok(op) => Some(op),
             Err(error) => {
-                // Make sure errors point at the constant.
-                self.ecx.set_span(c.span);
+                let tcx = self.ecx.tcx.at(c.span);
                 let err = error_to_const_error(&self.ecx, error);
                 if let Some(lint_root) = self.lint_root(source_info) {
                     let lint_only = match c.literal.val {
@@ -419,16 +418,16 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                         // Out of backwards compatibility we cannot report hard errors in unused
                         // generic functions using associated constants of the generic parameters.
                         err.report_as_lint(
-                            self.ecx.tcx,
+                            tcx,
                             "erroneous constant used",
                             lint_root,
                             Some(c.span),
                         );
                     } else {
-                        err.report_as_error(self.ecx.tcx, "erroneous constant used");
+                        err.report_as_error(tcx, "erroneous constant used");
                     }
                 } else {
-                    err.report_as_error(self.ecx.tcx, "erroneous constant used");
+                    err.report_as_error(tcx, "erroneous constant used");
                 }
                 None
             }
@@ -851,7 +850,6 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
     fn visit_statement(&mut self, statement: &mut Statement<'tcx>, location: Location) {
         trace!("visit_statement: {:?}", statement);
         let source_info = statement.source_info;
-        self.ecx.set_span(source_info.span);
         self.source_info = Some(source_info);
         if let StatementKind::Assign(box (place, ref mut rval)) = statement.kind {
             let place_ty: Ty<'tcx> = place.ty(&self.local_decls, self.tcx).ty;
@@ -864,7 +862,7 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
                         if let Some(value) = self.get_const(place) {
                             if self.should_const_prop(value) {
                                 trace!("replacing {:?} with {:?}", rval, value);
-                                self.replace_with_const(rval, value, statement.source_info);
+                                self.replace_with_const(rval, value, source_info);
                                 if can_const_prop == ConstPropMode::FullConstProp
                                     || can_const_prop == ConstPropMode::OnlyInsideOwnBlock
                                 {
@@ -927,7 +925,6 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
 
     fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, location: Location) {
         let source_info = terminator.source_info;
-        self.ecx.set_span(source_info.span);
         self.source_info = Some(source_info);
         self.super_terminator(terminator, location);
         match &mut terminator.kind {

From 0ac6fd0405c2f3defa9ad8ee3d4026469fbda018 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Mon, 1 Jun 2020 11:17:38 +0200
Subject: [PATCH 3/7] fix const_prop spans and re-bless tests

---
 src/librustc_mir/const_eval/error.rs          |  5 ++--
 src/librustc_mir/const_eval/eval_queries.rs   |  4 +--
 src/librustc_mir/interpret/cast.rs            |  7 ++---
 src/librustc_mir/interpret/eval_context.rs    |  6 ++---
 src/librustc_mir/interpret/place.rs           | 27 ++++++++++++++-----
 src/librustc_mir/transform/const_prop.rs      |  9 ++-----
 .../ui/consts/const-eval/infinite_loop.stderr |  4 +--
 .../const_eval_limit_reached.stderr           | 23 +++++++++-------
 .../recursive-zst-static.default.stderr       |  4 +--
 .../recursive-zst-static.unleash.stderr       |  4 +--
 .../consts/uninhabited-const-issue-61744.rs   |  4 +--
 .../uninhabited-const-issue-61744.stderr      |  8 +++---
 .../recursive-static-definition.stderr        |  4 +--
 .../ui/write-to-static-mut-in-static.stderr   |  4 +--
 14 files changed, 61 insertions(+), 52 deletions(-)

diff --git a/src/librustc_mir/const_eval/error.rs b/src/librustc_mir/const_eval/error.rs
index 2aafafd8205d1..5deae94fe0c8e 100644
--- a/src/librustc_mir/const_eval/error.rs
+++ b/src/librustc_mir/const_eval/error.rs
@@ -2,7 +2,7 @@ use std::error::Error;
 use std::fmt;
 
 use rustc_middle::mir::AssertKind;
-use rustc_span::Symbol;
+use rustc_span::{Span, Symbol};
 
 use super::InterpCx;
 use crate::interpret::{ConstEvalErr, InterpErrorInfo, Machine};
@@ -53,8 +53,9 @@ impl Error for ConstEvalErrKind {}
 pub fn error_to_const_error<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>>(
     ecx: &InterpCx<'mir, 'tcx, M>,
     error: InterpErrorInfo<'tcx>,
+    span: Option<Span>,
 ) -> ConstEvalErr<'tcx> {
     error.print_backtrace();
     let stacktrace = ecx.generate_stacktrace();
-    ConstEvalErr { error: error.kind, stacktrace, span: ecx.cur_span() }
+    ConstEvalErr { error: error.kind, stacktrace, span: span.unwrap_or_else(|| ecx.cur_span()) }
 }
diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs
index 4101ea77c9080..28e77bb57cd0c 100644
--- a/src/librustc_mir/const_eval/eval_queries.rs
+++ b/src/librustc_mir/const_eval/eval_queries.rs
@@ -213,7 +213,7 @@ fn validate_and_turn_into_const<'tcx>(
     })();
 
     val.map_err(|error| {
-        let err = error_to_const_error(&ecx, error);
+        let err = error_to_const_error(&ecx, error, None);
         err.struct_error(ecx.tcx_at(), "it is undefined behavior to use this value", |mut diag| {
             diag.note(note_on_undefined_behavior_error());
             diag.emit();
@@ -312,7 +312,7 @@ pub fn const_eval_raw_provider<'tcx>(
     res.and_then(|body| eval_body_using_ecx(&mut ecx, cid, &body))
         .map(|place| RawConst { alloc_id: place.ptr.assert_ptr().alloc_id, ty: place.layout.ty })
         .map_err(|error| {
-            let err = error_to_const_error(&ecx, error);
+            let err = error_to_const_error(&ecx, error, None);
             // errors in statics are always emitted as fatal errors
             if is_static {
                 // Ensure that if the above error was either `TooGeneric` or `Reported`
diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs
index 287b43ac50f96..793a67d804cec 100644
--- a/src/librustc_mir/interpret/cast.rs
+++ b/src/librustc_mir/interpret/cast.rs
@@ -268,11 +268,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             (&ty::Array(_, length), &ty::Slice(_)) => {
                 let ptr = self.read_immediate(src)?.to_scalar()?;
                 // u64 cast is from usize to u64, which is always good
-                let val = Immediate::new_slice(
-                    ptr,
-                    length.eval_usize(self.tcx, self.param_env),
-                    self,
-                );
+                let val =
+                    Immediate::new_slice(ptr, length.eval_usize(self.tcx, self.param_env), self);
                 self.write_immediate(val, dest)
             }
             (&ty::Dynamic(..), &ty::Dynamic(..)) => {
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 1715b6fede962..47e791854df48 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -314,8 +314,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
     #[inline(always)]
     pub fn cur_span(&self) -> Span {
-        self
-            .stack()
+        self.stack()
             .last()
             .and_then(|f| f.current_source_info())
             .map(|si| si.span)
@@ -419,7 +418,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         let did = instance.def_id();
         if let Some(did) = did.as_local() {
             if self.tcx_at().has_typeck_tables(did) {
-                if let Some(error_reported) = self.tcx_at().typeck_tables_of(did).tainted_by_errors {
+                if let Some(error_reported) = self.tcx_at().typeck_tables_of(did).tainted_by_errors
+                {
                     throw_inval!(TypeckError(error_reported))
                 }
             }
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index 0b4e92574a066..2477100eb8ad8 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -404,7 +404,10 @@ where
                     // to get some code to work that probably ought to work.
                     field_layout.align.abi
                 }
-                None => span_bug!(self.cur_span(), "cannot compute offset for extern type field at non-0 offset"),
+                None => span_bug!(
+                    self.cur_span(),
+                    "cannot compute offset for extern type field at non-0 offset"
+                ),
             };
             (base.meta, offset.align_to(align))
         } else {
@@ -440,7 +443,11 @@ where
                 assert!(!field_layout.is_unsized());
                 base.offset(offset, MemPlaceMeta::None, field_layout, self)
             }
-            _ => span_bug!(self.cur_span(), "`mplace_index` called on non-array type {:?}", base.layout.ty),
+            _ => span_bug!(
+                self.cur_span(),
+                "`mplace_index` called on non-array type {:?}",
+                base.layout.ty
+            ),
         }
     }
 
@@ -484,7 +491,9 @@ where
         // (that have count 0 in their layout).
         let from_offset = match base.layout.fields {
             FieldsShape::Array { stride, .. } => stride * from, // `Size` multiplication is checked
-            _ => span_bug!(self.cur_span(), "unexpected layout of index access: {:#?}", base.layout),
+            _ => {
+                span_bug!(self.cur_span(), "unexpected layout of index access: {:#?}", base.layout)
+            }
         };
 
         // Compute meta and new layout
@@ -497,7 +506,9 @@ where
                 let len = Scalar::from_machine_usize(inner_len, self);
                 (MemPlaceMeta::Meta(len), base.layout.ty)
             }
-            _ => span_bug!(self.cur_span(), "cannot subslice non-array type: `{:?}`", base.layout.ty),
+            _ => {
+                span_bug!(self.cur_span(), "cannot subslice non-array type: `{:?}`", base.layout.ty)
+            }
         };
         let layout = self.layout_of(ty)?;
         base.offset(from_offset, meta, layout, self)
@@ -776,9 +787,11 @@ where
             Immediate::Scalar(scalar) => {
                 match dest.layout.abi {
                     Abi::Scalar(_) => {} // fine
-                    _ => {
-                        span_bug!(self.cur_span(), "write_immediate_to_mplace: invalid Scalar layout: {:#?}", dest.layout)
-                    }
+                    _ => span_bug!(
+                        self.cur_span(),
+                        "write_immediate_to_mplace: invalid Scalar layout: {:#?}",
+                        dest.layout
+                    ),
                 }
                 self.memory.get_raw_mut(ptr.alloc_id)?.write_scalar(
                     &tcx,
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 133c05fc2f92b..d50f052d405bc 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -405,7 +405,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
             Ok(op) => Some(op),
             Err(error) => {
                 let tcx = self.ecx.tcx.at(c.span);
-                let err = error_to_const_error(&self.ecx, error);
+                let err = error_to_const_error(&self.ecx, error, Some(c.span));
                 if let Some(lint_root) = self.lint_root(source_info) {
                     let lint_only = match c.literal.val {
                         // Promoteds must lint and not error as the user didn't ask for them
@@ -417,12 +417,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                     if lint_only {
                         // Out of backwards compatibility we cannot report hard errors in unused
                         // generic functions using associated constants of the generic parameters.
-                        err.report_as_lint(
-                            tcx,
-                            "erroneous constant used",
-                            lint_root,
-                            Some(c.span),
-                        );
+                        err.report_as_lint(tcx, "erroneous constant used", lint_root, Some(c.span));
                     } else {
                         err.report_as_error(tcx, "erroneous constant used");
                     }
diff --git a/src/test/ui/consts/const-eval/infinite_loop.stderr b/src/test/ui/consts/const-eval/infinite_loop.stderr
index ebdb73c446791..3386e6e588e71 100644
--- a/src/test/ui/consts/const-eval/infinite_loop.stderr
+++ b/src/test/ui/consts/const-eval/infinite_loop.stderr
@@ -23,10 +23,10 @@ LL |             n = if n % 2 == 0 { n/2 } else { 3*n + 1 };
    = help: add `#![feature(const_if_match)]` to the crate attributes to enable
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/infinite_loop.rs:8:20
+  --> $DIR/infinite_loop.rs:8:17
    |
 LL |             n = if n % 2 == 0 { n/2 } else { 3*n + 1 };
-   |                    ^^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`)
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`)
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr b/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr
index be522dd6d5d5a..8c2190b4e591f 100644
--- a/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr
+++ b/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr
@@ -1,15 +1,18 @@
 error: any use of this value will cause an error
-  --> $DIR/const_eval_limit_reached.rs:8:11
+  --> $DIR/const_eval_limit_reached.rs:8:5
    |
-LL | / const X: usize = {
-LL | |     let mut x = 0;
-LL | |     while x != 1000 {
-   | |           ^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`)
-LL | |
-...  |
-LL | |     x
-LL | | };
-   | |__-
+LL |  / const X: usize = {
+LL |  |     let mut x = 0;
+LL |  |     while x != 1000 {
+   |  |_____^
+LL | ||
+LL | ||         x += 1;
+LL | ||     }
+   | ||_____^ exceeded interpreter step limit (see `#[const_eval_limit]`)
+LL |  |
+LL |  |     x
+LL |  | };
+   |  |__-
    |
    = note: `#[deny(const_err)]` on by default
 
diff --git a/src/test/ui/consts/recursive-zst-static.default.stderr b/src/test/ui/consts/recursive-zst-static.default.stderr
index d424b22f000bf..9042c6f6be191 100644
--- a/src/test/ui/consts/recursive-zst-static.default.stderr
+++ b/src/test/ui/consts/recursive-zst-static.default.stderr
@@ -1,8 +1,8 @@
 error[E0391]: cycle detected when const-evaluating `FOO`
-  --> $DIR/recursive-zst-static.rs:10:18
+  --> $DIR/recursive-zst-static.rs:10:1
    |
 LL | static FOO: () = FOO;
-   |                  ^^^
+   | ^^^^^^^^^^^^^^^^^^^^^
    |
 note: ...which requires const-evaluating `FOO`...
   --> $DIR/recursive-zst-static.rs:10:1
diff --git a/src/test/ui/consts/recursive-zst-static.unleash.stderr b/src/test/ui/consts/recursive-zst-static.unleash.stderr
index d424b22f000bf..9042c6f6be191 100644
--- a/src/test/ui/consts/recursive-zst-static.unleash.stderr
+++ b/src/test/ui/consts/recursive-zst-static.unleash.stderr
@@ -1,8 +1,8 @@
 error[E0391]: cycle detected when const-evaluating `FOO`
-  --> $DIR/recursive-zst-static.rs:10:18
+  --> $DIR/recursive-zst-static.rs:10:1
    |
 LL | static FOO: () = FOO;
-   |                  ^^^
+   | ^^^^^^^^^^^^^^^^^^^^^
    |
 note: ...which requires const-evaluating `FOO`...
   --> $DIR/recursive-zst-static.rs:10:1
diff --git a/src/test/ui/consts/uninhabited-const-issue-61744.rs b/src/test/ui/consts/uninhabited-const-issue-61744.rs
index 15436f9c1b2cf..55f42d84f9cb0 100644
--- a/src/test/ui/consts/uninhabited-const-issue-61744.rs
+++ b/src/test/ui/consts/uninhabited-const-issue-61744.rs
@@ -1,11 +1,11 @@
 // build-fail
 
 pub const unsafe fn fake_type<T>() -> T {
-    hint_unreachable()
+    hint_unreachable() //~ ERROR evaluation of constant value failed
 }
 
 pub const unsafe fn hint_unreachable() -> ! {
-    fake_type() //~ ERROR evaluation of constant value failed
+    fake_type()
 }
 
 trait Const {
diff --git a/src/test/ui/consts/uninhabited-const-issue-61744.stderr b/src/test/ui/consts/uninhabited-const-issue-61744.stderr
index ca232380897e3..fc908b2b2225f 100644
--- a/src/test/ui/consts/uninhabited-const-issue-61744.stderr
+++ b/src/test/ui/consts/uninhabited-const-issue-61744.stderr
@@ -1,9 +1,10 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
    |
 LL |     hint_unreachable()
-   |     ------------------
+   |     ^^^^^^^^^^^^^^^^^^
    |     |
+   |     reached the configured maximum number of stack frames
    |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
    |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
    |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
@@ -71,9 +72,8 @@ LL |     hint_unreachable()
    |     inside `fake_type::<i32>` at $DIR/uninhabited-const-issue-61744.rs:4:5
 ...
 LL |     fake_type()
-   |     ^^^^^^^^^^^
+   |     -----------
    |     |
-   |     reached the configured maximum number of stack frames
    |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
    |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
    |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
diff --git a/src/test/ui/recursion/recursive-static-definition.stderr b/src/test/ui/recursion/recursive-static-definition.stderr
index b724c261a7c3c..093606e100cb3 100644
--- a/src/test/ui/recursion/recursive-static-definition.stderr
+++ b/src/test/ui/recursion/recursive-static-definition.stderr
@@ -1,8 +1,8 @@
 error[E0391]: cycle detected when const-evaluating `FOO`
-  --> $DIR/recursive-static-definition.rs:1:23
+  --> $DIR/recursive-static-definition.rs:1:1
    |
 LL | pub static FOO: u32 = FOO;
-   |                       ^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: ...which requires const-evaluating `FOO`...
   --> $DIR/recursive-static-definition.rs:1:1
diff --git a/src/test/ui/write-to-static-mut-in-static.stderr b/src/test/ui/write-to-static-mut-in-static.stderr
index 6c2bd13d433ad..50dfce3448c34 100644
--- a/src/test/ui/write-to-static-mut-in-static.stderr
+++ b/src/test/ui/write-to-static-mut-in-static.stderr
@@ -5,10 +5,10 @@ LL | pub static mut B: () = unsafe { A = 1; };
    |                                 ^^^^^ modifying a static's initial value from another static's initializer
 
 error[E0391]: cycle detected when const-evaluating `C`
-  --> $DIR/write-to-static-mut-in-static.rs:5:34
+  --> $DIR/write-to-static-mut-in-static.rs:5:1
    |
 LL | pub static mut C: u32 = unsafe { C = 1; 0 };
-   |                                  ^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: ...which requires const-evaluating `C`...
   --> $DIR/write-to-static-mut-in-static.rs:5:1

From 32b01c78d0502c8a4cc36abbe8dc3c000436df98 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Thu, 11 Jun 2020 09:53:38 +0200
Subject: [PATCH 4/7] avoid computing cur_span all the time

---
 src/librustc_mir/const_eval/eval_queries.rs | 12 +++++++++---
 src/librustc_mir/interpret/eval_context.rs  |  8 +++++---
 2 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs
index 28e77bb57cd0c..310b09f71631e 100644
--- a/src/librustc_mir/const_eval/eval_queries.rs
+++ b/src/librustc_mir/const_eval/eval_queries.rs
@@ -317,7 +317,10 @@ pub fn const_eval_raw_provider<'tcx>(
             if is_static {
                 // Ensure that if the above error was either `TooGeneric` or `Reported`
                 // an error must be reported.
-                let v = err.report_as_error(ecx.tcx_at(), "could not evaluate static initializer");
+                let v = err.report_as_error(
+                    ecx.tcx.at(ecx.cur_span()),
+                    "could not evaluate static initializer",
+                );
 
                 // If this is `Reveal:All`, then we need to make sure an error is reported but if
                 // this is `Reveal::UserFacing`, then it's expected that we could get a
@@ -373,13 +376,16 @@ pub fn const_eval_raw_provider<'tcx>(
                         // anything else (array lengths, enum initializers, constant patterns) are
                         // reported as hard errors
                         } else {
-                            err.report_as_error(ecx.tcx_at(), "evaluation of constant value failed")
+                            err.report_as_error(
+                                ecx.tcx.at(ecx.cur_span()),
+                                "evaluation of constant value failed",
+                            )
                         }
                     }
                 }
             } else {
                 // use of broken constant from other crate
-                err.report_as_error(ecx.tcx_at(), "could not evaluate constant")
+                err.report_as_error(ecx.tcx.at(ecx.cur_span()), "could not evaluate constant")
             }
         })
 }
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 47e791854df48..866cdce7b77b6 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -323,7 +323,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
     #[inline(always)]
     pub fn tcx_at(&self) -> TyCtxtAt<'tcx> {
-        self.tcx.at(self.cur_span())
+        // Computing the current span has a non-trivial cost, and for cycle errors
+        // the "root span" is good enough.
+        self.tcx.at(self.root_span)
     }
 
     #[inline(always)]
@@ -406,7 +408,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
     #[inline]
     pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
-        ty.is_freeze(self.tcx, self.param_env, self.cur_span())
+        ty.is_freeze(self.tcx, self.param_env, self.root_span)
     }
 
     pub fn load_mir(
@@ -889,7 +891,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // FIXME: We can hit delay_span_bug if this is an invalid const, interning finds
         // that problem, but we never run validation to show an error. Can we ensure
         // this does not happen?
-        let val = self.tcx_at().const_eval_raw(param_env.and(gid))?;
+        let val = self.tcx.at(self.cur_span()).const_eval_raw(param_env.and(gid))?;
         self.raw_const_to_mplace(val)
     }
 

From 60496504ac635b3f805e8afed5eb6130b620f790 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Sat, 13 Jun 2020 13:47:37 +0200
Subject: [PATCH 5/7] avoid computing precise span for const_eval query

---
 src/librustc_mir/interpret/eval_context.rs    | 2 +-
 src/test/ui/consts/const-size_of-cycle.stderr | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 866cdce7b77b6..4a0981a95a666 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -860,7 +860,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         } else {
             self.param_env
         };
-        let val = self.tcx.const_eval_global_id(param_env, gid, Some(self.cur_span()))?;
+        let val = self.tcx.const_eval_global_id(param_env, gid, Some(self.root_span))?;
 
         // Even though `ecx.const_eval` is called from `eval_const_to_op` we can never have a
         // recursion deeper than one level, because the `tcx.const_eval` above is guaranteed to not
diff --git a/src/test/ui/consts/const-size_of-cycle.stderr b/src/test/ui/consts/const-size_of-cycle.stderr
index 5fd7fe4480e30..0aa30665f5907 100644
--- a/src/test/ui/consts/const-size_of-cycle.stderr
+++ b/src/test/ui/consts/const-size_of-cycle.stderr
@@ -17,8 +17,8 @@ LL |     bytes: [u8; std::mem::size_of::<Foo>()]
 note: ...which requires const-evaluating `std::mem::size_of`...
   --> $SRC_DIR/libcore/mem/mod.rs:LL:COL
    |
-LL |     intrinsics::size_of::<T>()
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | pub const fn size_of<T>() -> usize {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires const-evaluating + checking `std::intrinsics::size_of`...
   --> $SRC_DIR/libcore/intrinsics.rs:LL:COL
    |

From c6512fd4e959d1c19ee7b428a78696a53ab28bc6 Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Sat, 13 Jun 2020 13:55:01 +0200
Subject: [PATCH 6/7] run const_eval_raw with root_span

---
 src/librustc_mir/interpret/eval_context.rs              | 2 +-
 src/test/ui/infinite/infinite-recursion-const-fn.stderr | 8 ++++----
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 4a0981a95a666..5d344e9b372a0 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -891,7 +891,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // FIXME: We can hit delay_span_bug if this is an invalid const, interning finds
         // that problem, but we never run validation to show an error. Can we ensure
         // this does not happen?
-        let val = self.tcx.at(self.cur_span()).const_eval_raw(param_env.and(gid))?;
+        let val = self.tcx_at().const_eval_raw(param_env.and(gid))?;
         self.raw_const_to_mplace(val)
     }
 
diff --git a/src/test/ui/infinite/infinite-recursion-const-fn.stderr b/src/test/ui/infinite/infinite-recursion-const-fn.stderr
index 6bd5e035f5743..de0c579f63089 100644
--- a/src/test/ui/infinite/infinite-recursion-const-fn.stderr
+++ b/src/test/ui/infinite/infinite-recursion-const-fn.stderr
@@ -1,14 +1,14 @@
 error[E0391]: cycle detected when const-evaluating `a`
-  --> $DIR/infinite-recursion-const-fn.rs:3:25
+  --> $DIR/infinite-recursion-const-fn.rs:3:1
    |
 LL | const fn a() -> usize { b() }
-   |                         ^^^
+   | ^^^^^^^^^^^^^^^^^^^^^
    |
 note: ...which requires const-evaluating `b`...
-  --> $DIR/infinite-recursion-const-fn.rs:4:25
+  --> $DIR/infinite-recursion-const-fn.rs:4:1
    |
 LL | const fn b() -> usize { a() }
-   |                         ^^^
+   | ^^^^^^^^^^^^^^^^^^^^^
    = note: ...which again requires const-evaluating `a`, completing the cycle
 note: cycle used when const-evaluating `ARR::{{constant}}#0`
   --> $DIR/infinite-recursion-const-fn.rs:5:18

From 2210abea71270867fe2c69782f282c654e106fac Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Sun, 14 Jun 2020 15:02:51 +0200
Subject: [PATCH 7/7] keep root_span and tcx together

---
 src/librustc_mir/const_eval/eval_queries.rs   |  4 +-
 src/librustc_mir/interpret/cast.rs            |  8 ++--
 src/librustc_mir/interpret/eval_context.rs    | 47 +++++++------------
 src/librustc_mir/interpret/intern.rs          | 19 ++++----
 src/librustc_mir/interpret/intrinsics.rs      |  4 +-
 .../interpret/intrinsics/caller_location.rs   |  4 +-
 src/librustc_mir/interpret/operand.rs         | 16 +++----
 src/librustc_mir/interpret/place.rs           | 14 +++---
 src/librustc_mir/interpret/terminator.rs      |  8 ++--
 src/librustc_mir/interpret/traits.rs          |  8 ++--
 10 files changed, 60 insertions(+), 72 deletions(-)

diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs
index 310b09f71631e..d62300b3f5541 100644
--- a/src/librustc_mir/const_eval/eval_queries.rs
+++ b/src/librustc_mir/const_eval/eval_queries.rs
@@ -27,7 +27,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
     body: &'mir mir::Body<'tcx>,
 ) -> InterpResult<'tcx, MPlaceTy<'tcx>> {
     debug!("eval_body_using_ecx: {:?}, {:?}", cid, ecx.param_env);
-    let tcx = ecx.tcx;
+    let tcx = *ecx.tcx;
     let layout = ecx.layout_of(body.return_ty().subst(tcx, cid.instance.substs))?;
     assert!(!layout.is_unsized());
     let ret = ecx.allocate(layout, MemoryKind::Stack);
@@ -214,7 +214,7 @@ fn validate_and_turn_into_const<'tcx>(
 
     val.map_err(|error| {
         let err = error_to_const_error(&ecx, error, None);
-        err.struct_error(ecx.tcx_at(), "it is undefined behavior to use this value", |mut diag| {
+        err.struct_error(ecx.tcx, "it is undefined behavior to use this value", |mut diag| {
             diag.note(note_on_undefined_behavior_error());
             diag.emit();
         })
diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs
index 793a67d804cec..cfe856abe36dd 100644
--- a/src/librustc_mir/interpret/cast.rs
+++ b/src/librustc_mir/interpret/cast.rs
@@ -56,7 +56,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                         }
 
                         let instance = ty::Instance::resolve_for_fn_ptr(
-                            self.tcx,
+                            *self.tcx,
                             self.param_env,
                             def_id,
                             substs,
@@ -91,7 +91,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                         }
 
                         let instance = ty::Instance::resolve_closure(
-                            self.tcx,
+                            *self.tcx,
                             def_id,
                             substs,
                             ty::ClosureKind::FnOnce,
@@ -140,7 +140,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // Handle cast from a univariant (ZST) enum.
         match src.layout.variants {
             Variants::Single { index } => {
-                if let Some(discr) = src.layout.ty.discriminant_for_variant(self.tcx, index) {
+                if let Some(discr) = src.layout.ty.discriminant_for_variant(*self.tcx, index) {
                     assert!(src.layout.is_zst());
                     let discr_layout = self.layout_of(discr.ty)?;
                     return Ok(self.cast_from_scalar(discr.val, discr_layout, cast_ty).into());
@@ -269,7 +269,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let ptr = self.read_immediate(src)?.to_scalar()?;
                 // u64 cast is from usize to u64, which is always good
                 let val =
-                    Immediate::new_slice(ptr, length.eval_usize(self.tcx, self.param_env), self);
+                    Immediate::new_slice(ptr, length.eval_usize(*self.tcx, self.param_env), self);
                 self.write_immediate(val, dest)
             }
             (&ty::Dynamic(..), &ty::Dynamic(..)) => {
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 5d344e9b372a0..519dfd5b54e34 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -33,11 +33,9 @@ pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
     pub machine: M,
 
     /// The results of the type checker, from rustc.
-    pub tcx: TyCtxt<'tcx>,
-
-    /// The span of the "root" of the evaluation, i.e., the const
+    /// The span in this is the "root" of the evaluation, i.e., the const
     /// we are evaluating (if this is CTFE).
-    pub(super) root_span: Span,
+    pub tcx: TyCtxtAt<'tcx>,
 
     /// Bounds in scope for polymorphic evaluations.
     pub(crate) param_env: ty::ParamEnv<'tcx>,
@@ -200,7 +198,7 @@ where
 {
     #[inline]
     fn tcx(&self) -> TyCtxt<'tcx> {
-        self.tcx
+        *self.tcx
     }
 }
 
@@ -219,7 +217,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> LayoutOf for InterpCx<'mir, 'tcx,
 
     #[inline]
     fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyAndLayout {
-        self.tcx_at()
+        self.tcx
             .layout_of(self.param_env.and(ty))
             .map_err(|layout| err_inval!(Layout(layout)).into())
     }
@@ -304,8 +302,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     ) -> Self {
         InterpCx {
             machine,
-            tcx,
-            root_span,
+            tcx: tcx.at(root_span),
             param_env,
             memory: Memory::new(tcx, memory_extra),
             vtables: FxHashMap::default(),
@@ -318,14 +315,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             .last()
             .and_then(|f| f.current_source_info())
             .map(|si| si.span)
-            .unwrap_or(self.root_span)
-    }
-
-    #[inline(always)]
-    pub fn tcx_at(&self) -> TyCtxtAt<'tcx> {
-        // Computing the current span has a non-trivial cost, and for cycle errors
-        // the "root span" is good enough.
-        self.tcx.at(self.root_span)
+            .unwrap_or(self.tcx.span)
     }
 
     #[inline(always)]
@@ -403,12 +393,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
     #[inline]
     pub fn type_is_sized(&self, ty: Ty<'tcx>) -> bool {
-        ty.is_sized(self.tcx_at(), self.param_env)
+        ty.is_sized(self.tcx, self.param_env)
     }
 
     #[inline]
     pub fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
-        ty.is_freeze(self.tcx, self.param_env, self.root_span)
+        ty.is_freeze(*self.tcx, self.param_env, self.tcx.span)
     }
 
     pub fn load_mir(
@@ -419,21 +409,20 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // do not continue if typeck errors occurred (can only occur in local crate)
         let did = instance.def_id();
         if let Some(did) = did.as_local() {
-            if self.tcx_at().has_typeck_tables(did) {
-                if let Some(error_reported) = self.tcx_at().typeck_tables_of(did).tainted_by_errors
-                {
+            if self.tcx.has_typeck_tables(did) {
+                if let Some(error_reported) = self.tcx.typeck_tables_of(did).tainted_by_errors {
                     throw_inval!(TypeckError(error_reported))
                 }
             }
         }
         trace!("load mir(instance={:?}, promoted={:?})", instance, promoted);
         if let Some(promoted) = promoted {
-            return Ok(&self.tcx_at().promoted_mir(did)[promoted]);
+            return Ok(&self.tcx.promoted_mir(did)[promoted]);
         }
         match instance {
             ty::InstanceDef::Item(def_id) => {
-                if self.tcx_at().is_mir_available(did) {
-                    Ok(self.tcx_at().optimized_mir(did))
+                if self.tcx.is_mir_available(did) {
+                    Ok(self.tcx.optimized_mir(did))
                 } else {
                     throw_unsup!(NoMirFor(def_id))
                 }
@@ -474,7 +463,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         trace!("resolve: {:?}, {:#?}", def_id, substs);
         trace!("param_env: {:#?}", self.param_env);
         trace!("substs: {:#?}", substs);
-        match ty::Instance::resolve(self.tcx, self.param_env, def_id, substs) {
+        match ty::Instance::resolve(*self.tcx, self.param_env, def_id, substs) {
             Ok(Some(instance)) => Ok(instance),
             Ok(None) => throw_inval!(TooGeneric),
 
@@ -493,7 +482,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // have to support that case (mostly by skipping all caching).
         match frame.locals.get(local).and_then(|state| state.layout.get()) {
             None => {
-                let layout = from_known_layout(self.tcx_at(), layout, || {
+                let layout = from_known_layout(self.tcx, layout, || {
                     let local_ty = frame.body.local_decls[local].ty;
                     let local_ty =
                         self.subst_from_frame_and_normalize_erasing_regions(frame, local_ty);
@@ -645,7 +634,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         let mut locals = IndexVec::from_elem(dummy, &body.local_decls);
 
         // Now mark those locals as dead that we do not want to initialize
-        match self.tcx_at().def_kind(instance.def_id()) {
+        match self.tcx.def_kind(instance.def_id()) {
             // statics and constants don't have `Storage*` statements, no need to look for them
             //
             // FIXME: The above is likely untrue. See
@@ -860,7 +849,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         } else {
             self.param_env
         };
-        let val = self.tcx.const_eval_global_id(param_env, gid, Some(self.root_span))?;
+        let val = self.tcx.const_eval_global_id(param_env, gid, Some(self.tcx.span))?;
 
         // Even though `ecx.const_eval` is called from `eval_const_to_op` we can never have a
         // recursion deeper than one level, because the `tcx.const_eval` above is guaranteed to not
@@ -891,7 +880,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // FIXME: We can hit delay_span_bug if this is an invalid const, interning finds
         // that problem, but we never run validation to show an error. Can we ensure
         // this does not happen?
-        let val = self.tcx_at().const_eval_raw(param_env.and(gid))?;
+        let val = self.tcx.const_eval_raw(param_env.and(gid))?;
         self.raw_const_to_mplace(val)
     }
 
diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs
index 284a1d5ea61ef..3c724c79b4082 100644
--- a/src/librustc_mir/interpret/intern.rs
+++ b/src/librustc_mir/interpret/intern.rs
@@ -93,7 +93,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>(
             // in the value the dangling reference lies.
             // The `delay_span_bug` ensures that we don't forget such a check in validation.
             if tcx.get_global_alloc(alloc_id).is_none() {
-                tcx.sess.delay_span_bug(ecx.root_span, "tried to intern dangling pointer");
+                tcx.sess.delay_span_bug(ecx.tcx.span, "tried to intern dangling pointer");
             }
             // treat dangling pointers like other statics
             // just to stop trying to recurse into them
@@ -111,7 +111,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>(
     if let InternMode::Static(mutability) = mode {
         // For this, we need to take into account `UnsafeCell`. When `ty` is `None`, we assume
         // no interior mutability.
-        let frozen = ty.map_or(true, |ty| ty.is_freeze(ecx.tcx, ecx.param_env, ecx.root_span));
+        let frozen = ty.map_or(true, |ty| ty.is_freeze(*ecx.tcx, ecx.param_env, ecx.tcx.span));
         // For statics, allocation mutability is the combination of the place mutability and
         // the type mutability.
         // The entire allocation needs to be mutable if it contains an `UnsafeCell` anywhere.
@@ -174,7 +174,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir
                     // they caused.  It also helps us to find cases where const-checking
                     // failed to prevent an `UnsafeCell` (but as `ignore_interior_mut_in_const`
                     // shows that part is not airtight).
-                    mutable_memory_in_const(self.ecx.tcx_at(), "`UnsafeCell`");
+                    mutable_memory_in_const(self.ecx.tcx, "`UnsafeCell`");
                 }
                 // We are crossing over an `UnsafeCell`, we can mutate again. This means that
                 // References we encounter inside here are interned as pointing to mutable
@@ -192,7 +192,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir
     fn visit_value(&mut self, mplace: MPlaceTy<'tcx>) -> InterpResult<'tcx> {
         // Handle Reference types, as these are the only relocations supported by const eval.
         // Raw pointers (and boxes) are handled by the `leftover_relocations` logic.
-        let tcx = self.ecx.tcx.at(self.ecx.root_span);
+        let tcx = self.ecx.tcx;
         let ty = mplace.layout.ty;
         if let ty::Ref(_, referenced_ty, ref_mutability) = ty.kind {
             let value = self.ecx.read_immediate(mplace.into())?;
@@ -253,8 +253,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir
                         // caused (by somehow getting a mutable reference in a `const`).
                         if ref_mutability == Mutability::Mut {
                             match referenced_ty.kind {
-                                ty::Array(_, n)
-                                    if n.eval_usize(self.ecx.tcx, self.ecx.param_env) == 0 => {}
+                                ty::Array(_, n) if n.eval_usize(*tcx, self.ecx.param_env) == 0 => {}
                                 ty::Slice(_)
                                     if mplace.meta.unwrap_meta().to_machine_usize(self.ecx)?
                                         == 0 => {}
@@ -358,7 +357,7 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
             Ok(()) => {}
             Err(error) => {
                 ecx.tcx.sess.delay_span_bug(
-                    ecx.root_span,
+                    ecx.tcx.span,
                     "error during interning should later cause validation failure",
                 );
                 // Some errors shouldn't come up because creating them causes
@@ -407,7 +406,7 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
                     // such as `const CONST_RAW: *const Vec<i32> = &Vec::new() as *const _;`.
                     ecx.tcx
                         .sess
-                        .span_err(ecx.root_span, "untyped pointers are not allowed in constant");
+                        .span_err(ecx.tcx.span, "untyped pointers are not allowed in constant");
                     // For better errors later, mark the allocation as immutable.
                     alloc.mutability = Mutability::Not;
                 }
@@ -422,11 +421,11 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
         } else if ecx.memory.dead_alloc_map.contains_key(&alloc_id) {
             // Codegen does not like dangling pointers, and generally `tcx` assumes that
             // all allocations referenced anywhere actually exist. So, make sure we error here.
-            ecx.tcx.sess.span_err(ecx.root_span, "encountered dangling pointer in final constant");
+            ecx.tcx.sess.span_err(ecx.tcx.span, "encountered dangling pointer in final constant");
         } else if ecx.tcx.get_global_alloc(alloc_id).is_none() {
             // We have hit an `AllocId` that is neither in local or global memory and isn't
             // marked as dangling by local memory.  That should be impossible.
-            span_bug!(ecx.root_span, "encountered unknown alloc id {:?}", alloc_id);
+            span_bug!(ecx.tcx.span, "encountered unknown alloc id {:?}", alloc_id);
         }
     }
 }
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index c62fd316dc584..47e5b8b4fcec4 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -347,7 +347,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let index = u64::from(self.read_scalar(args[1])?.to_u32()?);
                 let elem = args[2];
                 let input = args[0];
-                let (len, e_ty) = input.layout.ty.simd_size_and_type(self.tcx);
+                let (len, e_ty) = input.layout.ty.simd_size_and_type(*self.tcx);
                 assert!(
                     index < len,
                     "Index `{}` must be in bounds of vector type `{}`: `[0, {})`",
@@ -374,7 +374,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             }
             sym::simd_extract => {
                 let index = u64::from(self.read_scalar(args[1])?.to_u32()?);
-                let (len, e_ty) = args[0].layout.ty.simd_size_and_type(self.tcx);
+                let (len, e_ty) = args[0].layout.ty.simd_size_and_type(*self.tcx);
                 assert!(
                     index < len,
                     "index `{}` is out-of-bounds of vector type `{}` with length `{}`",
diff --git a/src/librustc_mir/interpret/intrinsics/caller_location.rs b/src/librustc_mir/interpret/intrinsics/caller_location.rs
index 193d38dc5523e..ddeed92f85124 100644
--- a/src/librustc_mir/interpret/intrinsics/caller_location.rs
+++ b/src/librustc_mir/interpret/intrinsics/caller_location.rs
@@ -25,7 +25,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     "find_closest_untracked_caller_location: checking frame {:?}",
                     frame.instance
                 );
-                !frame.instance.def.requires_caller_location(self.tcx)
+                !frame.instance.def.requires_caller_location(*self.tcx)
             })
             // Assert that there is always such a frame.
             .unwrap();
@@ -58,7 +58,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         let loc_ty = self
             .tcx
             .type_of(self.tcx.require_lang_item(PanicLocationLangItem, None))
-            .subst(self.tcx, self.tcx.mk_substs([self.tcx.lifetimes.re_erased.into()].iter()));
+            .subst(*self.tcx, self.tcx.mk_substs([self.tcx.lifetimes.re_erased.into()].iter()));
         let loc_layout = self.layout_of(loc_ty).unwrap();
         let location = self.allocate(loc_layout, MemoryKind::CallerLocation);
 
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index c9250098fedba..38f5988d0eb3f 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -471,9 +471,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         trace!("eval_place_to_op: got {:?}", *op);
         // Sanity-check the type we ended up with.
         debug_assert!(mir_assign_valid_types(
-            self.tcx,
+            *self.tcx,
             self.layout_of(self.subst_from_current_frame_and_normalize_erasing_regions(
-                place.ty(&self.frame().body.local_decls, self.tcx).ty
+                place.ty(&self.frame().body.local_decls, *self.tcx).ty
             ))?,
             op.layout,
         ));
@@ -554,7 +554,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // documentation).
         let val_val = M::adjust_global_const(self, val_val)?;
         // Other cases need layout.
-        let layout = from_known_layout(self.tcx_at(), layout, || self.layout_of(val.ty))?;
+        let layout = from_known_layout(self.tcx, layout, || self.layout_of(val.ty))?;
         let op = match val_val {
             ConstValue::ByRef { alloc, offset } => {
                 let id = self.tcx.create_memory_alloc(alloc);
@@ -589,7 +589,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         trace!("read_discriminant_value {:#?}", op.layout);
 
         // Get type and layout of the discriminant.
-        let discr_layout = self.layout_of(op.layout.ty.discriminant_ty(self.tcx))?;
+        let discr_layout = self.layout_of(op.layout.ty.discriminant_ty(*self.tcx))?;
         trace!("discriminant type: {:?}", discr_layout.ty);
 
         // We use "discriminant" to refer to the value associated with a particular enum variant.
@@ -601,7 +601,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // rather confusing.
         let (tag_scalar_layout, tag_kind, tag_index) = match op.layout.variants {
             Variants::Single { index } => {
-                let discr = match op.layout.ty.discriminant_for_variant(self.tcx, index) {
+                let discr = match op.layout.ty.discriminant_for_variant(*self.tcx, index) {
                     Some(discr) => {
                         // This type actually has discriminants.
                         assert_eq!(discr.ty, discr_layout.ty);
@@ -630,7 +630,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         //   may be a pointer. This is `tag_val.layout`; we just use it for sanity checks.
 
         // Get layout for tag.
-        let tag_layout = self.layout_of(tag_scalar_layout.value.to_int_ty(self.tcx))?;
+        let tag_layout = self.layout_of(tag_scalar_layout.value.to_int_ty(*self.tcx))?;
 
         // Read tag and sanity-check `tag_layout`.
         let tag_val = self.read_immediate(self.operand_field(op, tag_index)?)?;
@@ -651,12 +651,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 // Convert discriminant to variant index, and catch invalid discriminants.
                 let index = match op.layout.ty.kind {
                     ty::Adt(adt, _) => {
-                        adt.discriminants(self.tcx).find(|(_, var)| var.val == discr_bits)
+                        adt.discriminants(*self.tcx).find(|(_, var)| var.val == discr_bits)
                     }
                     ty::Generator(def_id, substs, _) => {
                         let substs = substs.as_generator();
                         substs
-                            .discriminants(def_id, self.tcx)
+                            .discriminants(def_id, *self.tcx)
                             .find(|(_, var)| var.val == discr_bits)
                     }
                     _ => bug!("tagged layout for non-adt non-generator"),
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index 2477100eb8ad8..24b191e9b535a 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -651,9 +651,9 @@ where
         self.dump_place(place_ty.place);
         // Sanity-check the type we ended up with.
         debug_assert!(mir_assign_valid_types(
-            self.tcx,
+            *self.tcx,
             self.layout_of(self.subst_from_current_frame_and_normalize_erasing_regions(
-                place.ty(&self.frame().body.local_decls, self.tcx).ty
+                place.ty(&self.frame().body.local_decls, *self.tcx).ty
             ))?,
             place_ty.layout,
         ));
@@ -779,7 +779,7 @@ where
             None => return Ok(()), // zero-sized access
         };
 
-        let tcx = self.tcx;
+        let tcx = *self.tcx;
         // FIXME: We should check that there are dest.layout.size many bytes available in
         // memory.  The code below is not sufficient, with enough padding it might not
         // cover all the bytes!
@@ -855,7 +855,7 @@ where
     ) -> InterpResult<'tcx> {
         // We do NOT compare the types for equality, because well-typed code can
         // actually "transmute" `&mut T` to `&T` in an assignment without a cast.
-        if !mir_assign_valid_types(self.tcx, src.layout, dest.layout) {
+        if !mir_assign_valid_types(*self.tcx, src.layout, dest.layout) {
             span_bug!(
                 self.cur_span(),
                 "type mismatch when copying!\nsrc: {:?},\ndest: {:?}",
@@ -912,7 +912,7 @@ where
         src: OpTy<'tcx, M::PointerTag>,
         dest: PlaceTy<'tcx, M::PointerTag>,
     ) -> InterpResult<'tcx> {
-        if mir_assign_valid_types(self.tcx, src.layout, dest.layout) {
+        if mir_assign_valid_types(*self.tcx, src.layout, dest.layout) {
             // Fast path: Just use normal `copy_op`
             return self.copy_op(src, dest);
         }
@@ -1070,7 +1070,7 @@ where
                 // `TyAndLayout::for_variant()` call earlier already checks the variant is valid.
 
                 let discr_val =
-                    dest.layout.ty.discriminant_for_variant(self.tcx, variant_index).unwrap().val;
+                    dest.layout.ty.discriminant_for_variant(*self.tcx, variant_index).unwrap().val;
 
                 // raw discriminants for enums are isize or bigger during
                 // their computation, but the in-memory tag is the smallest possible
@@ -1099,7 +1099,7 @@ where
                         .expect("overflow computing relative variant idx");
                     // We need to use machine arithmetic when taking into account `niche_start`:
                     // discr_val = variant_index_relative + niche_start_val
-                    let discr_layout = self.layout_of(discr_layout.value.to_int_ty(self.tcx))?;
+                    let discr_layout = self.layout_of(discr_layout.value.to_int_ty(*self.tcx))?;
                     let niche_start_val = ImmTy::from_uint(niche_start, discr_layout);
                     let variant_index_relative_val =
                         ImmTy::from_uint(variant_index_relative, discr_layout);
diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs
index 9a4dd0a5204f9..cd7621ea9752b 100644
--- a/src/librustc_mir/interpret/terminator.rs
+++ b/src/librustc_mir/interpret/terminator.rs
@@ -69,7 +69,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                         (fn_val, caller_abi)
                     }
                     ty::FnDef(def_id, substs) => {
-                        let sig = func.layout.ty.fn_sig(self.tcx);
+                        let sig = func.layout.ty.fn_sig(*self.tcx);
                         (FnVal::Instance(self.resolve(def_id, substs)?), sig.abi())
                     }
                     _ => span_bug!(
@@ -96,7 +96,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let ty = place.layout.ty;
                 trace!("TerminatorKind::drop: {:?}, type {}", location, ty);
 
-                let instance = Instance::resolve_drop_in_place(self.tcx, ty);
+                let instance = Instance::resolve_drop_in_place(*self.tcx, ty);
                 self.drop_in_place(place, instance, target, unwind)?;
             }
 
@@ -227,9 +227,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // ABI check
         {
             let callee_abi = {
-                let instance_ty = instance.ty_env(self.tcx, self.param_env);
+                let instance_ty = instance.ty_env(*self.tcx, self.param_env);
                 match instance_ty.kind {
-                    ty::FnDef(..) => instance_ty.fn_sig(self.tcx).abi(),
+                    ty::FnDef(..) => instance_ty.fn_sig(*self.tcx).abi(),
                     ty::Closure(..) => Abi::RustCall,
                     ty::Generator(..) => Abi::Rust,
                     _ => bug!("unexpected callee ty: {:?}", instance_ty),
diff --git a/src/librustc_mir/interpret/traits.rs b/src/librustc_mir/interpret/traits.rs
index 87493a8d383ec..a1d124bb7602e 100644
--- a/src/librustc_mir/interpret/traits.rs
+++ b/src/librustc_mir/interpret/traits.rs
@@ -36,10 +36,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         }
 
         let methods = if let Some(poly_trait_ref) = poly_trait_ref {
-            let trait_ref = poly_trait_ref.with_self_ty(self.tcx, ty);
+            let trait_ref = poly_trait_ref.with_self_ty(*self.tcx, ty);
             let trait_ref = self.tcx.erase_regions(&trait_ref);
 
-            self.tcx_at().vtable_methods(trait_ref)
+            self.tcx.vtable_methods(trait_ref)
         } else {
             &[]
         };
@@ -49,7 +49,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         let size = layout.size.bytes();
         let align = layout.align.abi.bytes();
 
-        let tcx = self.tcx;
+        let tcx = *self.tcx;
         let ptr_size = self.pointer_size();
         let ptr_align = tcx.data_layout.pointer_align.abi;
         // /////////////////////////////////////////////////////////////////////////////////////////
@@ -142,7 +142,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // to determine the type.
         let drop_instance = self.memory.get_fn(drop_fn)?.as_instance()?;
         trace!("Found drop fn: {:?}", drop_instance);
-        let fn_sig = drop_instance.ty_env(self.tcx, self.param_env).fn_sig(self.tcx);
+        let fn_sig = drop_instance.ty_env(*self.tcx, self.param_env).fn_sig(*self.tcx);
         let fn_sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, &fn_sig);
         // The drop function takes `*mut T` where `T` is the type being dropped, so get that.
         let args = fn_sig.inputs();