about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/mir/interpret/error.rs146
-rw-r--r--src/librustc/mir/interpret/mod.rs20
-rw-r--r--src/librustc/mir/mod.rs67
-rw-r--r--src/librustc/mir/visit.rs4
-rw-r--r--src/librustc_codegen_ssa/mir/block.rs6
-rw-r--r--src/librustc_mir/borrow_check/invalidation.rs4
-rw-r--r--src/librustc_mir/borrow_check/mod.rs4
-rw-r--r--src/librustc_mir/borrow_check/type_check/mod.rs4
-rw-r--r--src/librustc_mir/const_eval/error.rs28
-rw-r--r--src/librustc_mir/const_eval/machine.rs78
-rw-r--r--src/librustc_mir/interpret/intrinsics.rs26
-rw-r--r--src/librustc_mir/interpret/intrinsics/caller_location.rs12
-rw-r--r--src/librustc_mir/interpret/machine.rs6
-rw-r--r--src/librustc_mir/transform/const_prop.rs124
-rw-r--r--src/librustc_mir/transform/generator.rs2
-rw-r--r--src/librustc_mir_build/build/expr/as_place.rs2
-rw-r--r--src/librustc_mir_build/build/expr/as_rvalue.rs12
17 files changed, 271 insertions, 274 deletions
diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs
index 86e7bb28e00..e747eee30f9 100644
--- a/src/librustc/mir/interpret/error.rs
+++ b/src/librustc/mir/interpret/error.rs
@@ -7,11 +7,9 @@ use crate::ty::query::TyCtxtAt;
 use crate::ty::{self, layout, Ty};
 
 use backtrace::Backtrace;
-use hir::GeneratorKind;
 use rustc_errors::{struct_span_err, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_macros::HashStable;
-use rustc_span::symbol::Symbol;
 use rustc_span::{Pos, Span};
 use rustc_target::spec::abi::Abi;
 use std::{any::Any, env, fmt};
@@ -128,9 +126,15 @@ impl<'tcx> ConstEvalErr<'tcx> {
         }
     }
 
-    /// Sets the message passed in via `message` and adds span labels before handing control back
-    /// to `emit` to do any final processing. It's the caller's responsibility to call emit(),
-    /// stash(), etc. within the `emit` function to dispose of the diagnostic properly.
+    /// Create a diagnostic for this const eval error.
+    ///
+    /// Sets the message passed in via `message` and adds span labels with detailed error
+    /// information before handing control back to `emit` to do any final processing.
+    /// It's the caller's responsibility to call emit(), stash(), etc. within the `emit`
+    /// function to dispose of the diagnostic properly.
+    ///
+    /// If `lint_root.is_some()` report it as a lint, else report it as a hard error.
+    /// (Except that for some errors, we ignore all that -- see `must_error` below.)
     fn struct_generic(
         &self,
         tcx: TyCtxtAt<'tcx>,
@@ -139,20 +143,30 @@ impl<'tcx> ConstEvalErr<'tcx> {
         lint_root: Option<hir::HirId>,
     ) -> Result<(), ErrorHandled> {
         let must_error = match self.error {
-            InterpError::MachineStop(_) => bug!("CTFE does not stop"),
             err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => {
                 return Err(ErrorHandled::TooGeneric);
             }
             err_inval!(TypeckError) => return Err(ErrorHandled::Reported),
+            // We must *always* hard error on these, even if the caller wants just a lint.
             err_inval!(Layout(LayoutError::SizeOverflow(_))) => true,
             _ => false,
         };
         trace!("reporting const eval failure at {:?}", self.span);
 
-        let add_span_labels = |err: &mut DiagnosticBuilder<'_>| {
-            if !must_error {
-                err.span_label(self.span, self.error.to_string());
+        let err_msg = match &self.error {
+            InterpError::MachineStop(msg) => {
+                // A custom error (`ConstEvalErrKind` in `librustc_mir/interp/const_eval/error.rs`).
+                // Should be turned into a string by now.
+                msg.downcast_ref::<String>().expect("invalid MachineStop payload").clone()
             }
+            err => err.to_string(),
+        };
+
+        let finish = |mut err: DiagnosticBuilder<'_>, span_msg: Option<String>| {
+            if let Some(span_msg) = span_msg {
+                err.span_label(self.span, span_msg);
+            }
+            // Add spans for the stacktrace.
             // Skip the last, which is just the environment of the constant.  The stacktrace
             // is sometimes empty because we create "fake" eval contexts in CTFE to do work
             // on constant values.
@@ -161,35 +175,37 @@ impl<'tcx> ConstEvalErr<'tcx> {
                     err.span_label(frame_info.call_site, frame_info.to_string());
                 }
             }
+            // Let the caller finish the job.
+            emit(err)
         };
 
-        if let (Some(lint_root), false) = (lint_root, must_error) {
-            let hir_id = self
-                .stacktrace
-                .iter()
-                .rev()
-                .filter_map(|frame| frame.lint_root)
-                .next()
-                .unwrap_or(lint_root);
-            tcx.struct_span_lint_hir(
-                rustc_session::lint::builtin::CONST_ERR,
-                hir_id,
-                tcx.span,
-                |lint| {
-                    let mut err = lint.build(message);
-                    add_span_labels(&mut err);
-                    emit(err);
-                },
-            );
+        if must_error {
+            // The `message` makes little sense here, this is a more serious error than the
+            // caller thinks anyway.
+            // See <https://github.com/rust-lang/rust/pull/63152>.
+            finish(struct_error(tcx, &err_msg), None);
         } else {
-            let mut err = if must_error {
-                struct_error(tcx, &self.error.to_string())
+            // Regular case.
+            if let Some(lint_root) = lint_root {
+                // Report as lint.
+                let hir_id = self
+                    .stacktrace
+                    .iter()
+                    .rev()
+                    .filter_map(|frame| frame.lint_root)
+                    .next()
+                    .unwrap_or(lint_root);
+                tcx.struct_span_lint_hir(
+                    rustc_session::lint::builtin::CONST_ERR,
+                    hir_id,
+                    tcx.span,
+                    |lint| finish(lint.build(message), Some(err_msg)),
+                );
             } else {
-                struct_error(tcx, message)
-            };
-            add_span_labels(&mut err);
-            emit(err);
-        };
+                // Report as hard error.
+                finish(struct_error(tcx, message), Some(err_msg));
+            }
+        }
         Ok(())
     }
 }
@@ -259,63 +275,6 @@ impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, PartialEq)]
-pub enum PanicInfo<O> {
-    Panic { msg: Symbol, line: u32, col: u32, file: Symbol },
-    BoundsCheck { len: O, index: O },
-    Overflow(mir::BinOp),
-    OverflowNeg,
-    DivisionByZero,
-    RemainderByZero,
-    ResumedAfterReturn(GeneratorKind),
-    ResumedAfterPanic(GeneratorKind),
-}
-
-/// Type for MIR `Assert` terminator error messages.
-pub type AssertMessage<'tcx> = PanicInfo<mir::Operand<'tcx>>;
-
-impl<O> PanicInfo<O> {
-    /// Getting a description does not require `O` to be printable, and does not
-    /// require allocation.
-    /// The caller is expected to handle `Panic` and `BoundsCheck` separately.
-    pub fn description(&self) -> &'static str {
-        use PanicInfo::*;
-        match self {
-            Overflow(mir::BinOp::Add) => "attempt to add with overflow",
-            Overflow(mir::BinOp::Sub) => "attempt to subtract with overflow",
-            Overflow(mir::BinOp::Mul) => "attempt to multiply with overflow",
-            Overflow(mir::BinOp::Div) => "attempt to divide with overflow",
-            Overflow(mir::BinOp::Rem) => "attempt to calculate the remainder with overflow",
-            OverflowNeg => "attempt to negate with overflow",
-            Overflow(mir::BinOp::Shr) => "attempt to shift right with overflow",
-            Overflow(mir::BinOp::Shl) => "attempt to shift left with overflow",
-            Overflow(op) => bug!("{:?} cannot overflow", op),
-            DivisionByZero => "attempt to divide by zero",
-            RemainderByZero => "attempt to calculate the remainder with a divisor of zero",
-            ResumedAfterReturn(GeneratorKind::Gen) => "generator resumed after completion",
-            ResumedAfterReturn(GeneratorKind::Async(_)) => "`async fn` resumed after completion",
-            ResumedAfterPanic(GeneratorKind::Gen) => "generator resumed after panicking",
-            ResumedAfterPanic(GeneratorKind::Async(_)) => "`async fn` resumed after panicking",
-            Panic { .. } | BoundsCheck { .. } => bug!("Unexpected PanicInfo"),
-        }
-    }
-}
-
-impl<O: fmt::Debug> fmt::Debug for PanicInfo<O> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use PanicInfo::*;
-        match self {
-            Panic { ref msg, line, col, ref file } => {
-                write!(f, "the evaluated program panicked at '{}', {}:{}:{}", msg, file, line, col)
-            }
-            BoundsCheck { ref len, ref index } => {
-                write!(f, "index out of bounds: the len is {:?} but the index is {:?}", len, index)
-            }
-            _ => write!(f, "{}", self.description()),
-        }
-    }
-}
-
 /// Error information for when the program we executed turned out not to actually be a valid
 /// program. This cannot happen in stand-alone Miri, but it can happen during CTFE/ConstProp
 /// where we work on generic code or execution does not have all information available.
@@ -616,8 +575,6 @@ impl fmt::Debug for ResourceExhaustionInfo {
 }
 
 pub enum InterpError<'tcx> {
-    /// The program panicked.
-    Panic(PanicInfo<u64>),
     /// The program caused undefined behavior.
     UndefinedBehavior(UndefinedBehaviorInfo),
     /// The program did something the interpreter does not support (some of these *might* be UB
@@ -650,8 +607,7 @@ impl fmt::Debug for InterpError<'_> {
             InvalidProgram(ref msg) => write!(f, "{:?}", msg),
             UndefinedBehavior(ref msg) => write!(f, "{:?}", msg),
             ResourceExhaustion(ref msg) => write!(f, "{:?}", msg),
-            Panic(ref msg) => write!(f, "{:?}", msg),
-            MachineStop(_) => write!(f, "machine caused execution to stop"),
+            MachineStop(_) => bug!("unhandled MachineStop"),
         }
     }
 }
diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs
index 54e196f4b33..f0879bdd8ae 100644
--- a/src/librustc/mir/interpret/mod.rs
+++ b/src/librustc/mir/interpret/mod.rs
@@ -38,15 +38,6 @@ macro_rules! err_ub_format {
 }
 
 #[macro_export]
-macro_rules! err_panic {
-    ($($tt:tt)*) => {
-        $crate::mir::interpret::InterpError::Panic(
-            $crate::mir::interpret::PanicInfo::$($tt)*
-        )
-    };
-}
-
-#[macro_export]
 macro_rules! err_exhaust {
     ($($tt:tt)*) => {
         $crate::mir::interpret::InterpError::ResourceExhaustion(
@@ -81,11 +72,6 @@ macro_rules! throw_ub_format {
 }
 
 #[macro_export]
-macro_rules! throw_panic {
-    ($($tt:tt)*) => { return Err(err_panic!($($tt)*).into()) };
-}
-
-#[macro_export]
 macro_rules! throw_exhaust {
     ($($tt:tt)*) => { return Err(err_exhaust!($($tt)*).into()) };
 }
@@ -104,9 +90,9 @@ mod queries;
 mod value;
 
 pub use self::error::{
-    struct_error, AssertMessage, ConstEvalErr, ConstEvalRawResult, ConstEvalResult, ErrorHandled,
-    FrameInfo, InterpError, InterpErrorInfo, InterpResult, InvalidProgramInfo, PanicInfo,
-    ResourceExhaustionInfo, UndefinedBehaviorInfo, UnsupportedOpInfo,
+    struct_error, ConstEvalErr, ConstEvalRawResult, ConstEvalResult, ErrorHandled, FrameInfo,
+    InterpError, InterpErrorInfo, InterpResult, InvalidProgramInfo, ResourceExhaustionInfo,
+    UndefinedBehaviorInfo, UnsupportedOpInfo,
 };
 
 pub use self::value::{get_slice_bytes, ConstValue, RawConst, Scalar, ScalarMaybeUndef};
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index f6c7174649f..4520d3a3333 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -2,7 +2,7 @@
 //!
 //! [rustc guide]: https://rust-lang.github.io/rustc-guide/mir/index.html
 
-use crate::mir::interpret::{GlobalAlloc, PanicInfo, Scalar};
+use crate::mir::interpret::{GlobalAlloc, Scalar};
 use crate::mir::visit::MirVisitable;
 use crate::ty::adjustment::PointerCast;
 use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
@@ -36,7 +36,6 @@ pub use syntax::ast::Mutability;
 use syntax::ast::Name;
 
 pub use self::cache::{BodyAndCache, ReadOnlyBodyAndCache};
-pub use self::interpret::AssertMessage;
 pub use self::query::*;
 pub use crate::read_only;
 
@@ -1154,6 +1153,21 @@ pub enum TerminatorKind<'tcx> {
     },
 }
 
+/// Information about an assertion failure.
+#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, PartialEq)]
+pub enum AssertKind<O> {
+    BoundsCheck { len: O, index: O },
+    Overflow(BinOp),
+    OverflowNeg,
+    DivisionByZero,
+    RemainderByZero,
+    ResumedAfterReturn(GeneratorKind),
+    ResumedAfterPanic(GeneratorKind),
+}
+
+/// Type for MIR `Assert` terminator error messages.
+pub type AssertMessage<'tcx> = AssertKind<Operand<'tcx>>;
+
 pub type Successors<'a> =
     iter::Chain<option::IntoIter<&'a BasicBlock>, slice::Iter<'a, BasicBlock>>;
 pub type SuccessorsMut<'a> =
@@ -1383,6 +1397,45 @@ impl<'tcx> BasicBlockData<'tcx> {
     }
 }
 
+impl<O> AssertKind<O> {
+    /// Getting a description does not require `O` to be printable, and does not
+    /// require allocation.
+    /// The caller is expected to handle `BoundsCheck` separately.
+    pub fn description(&self) -> &'static str {
+        use AssertKind::*;
+        match self {
+            Overflow(BinOp::Add) => "attempt to add with overflow",
+            Overflow(BinOp::Sub) => "attempt to subtract with overflow",
+            Overflow(BinOp::Mul) => "attempt to multiply with overflow",
+            Overflow(BinOp::Div) => "attempt to divide with overflow",
+            Overflow(BinOp::Rem) => "attempt to calculate the remainder with overflow",
+            OverflowNeg => "attempt to negate with overflow",
+            Overflow(BinOp::Shr) => "attempt to shift right with overflow",
+            Overflow(BinOp::Shl) => "attempt to shift left with overflow",
+            Overflow(op) => bug!("{:?} cannot overflow", op),
+            DivisionByZero => "attempt to divide by zero",
+            RemainderByZero => "attempt to calculate the remainder with a divisor of zero",
+            ResumedAfterReturn(GeneratorKind::Gen) => "generator resumed after completion",
+            ResumedAfterReturn(GeneratorKind::Async(_)) => "`async fn` resumed after completion",
+            ResumedAfterPanic(GeneratorKind::Gen) => "generator resumed after panicking",
+            ResumedAfterPanic(GeneratorKind::Async(_)) => "`async fn` resumed after panicking",
+            BoundsCheck { .. } => bug!("Unexpected AssertKind"),
+        }
+    }
+}
+
+impl<O: fmt::Debug> fmt::Debug for AssertKind<O> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use AssertKind::*;
+        match self {
+            BoundsCheck { ref len, ref index } => {
+                write!(f, "index out of bounds: the len is {:?} but the index is {:?}", len, index)
+            }
+            _ => write!(f, "{}", self.description()),
+        }
+    }
+}
+
 impl<'tcx> Debug for TerminatorKind<'tcx> {
     fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
         self.fmt_head(fmt)?;
@@ -2666,13 +2719,12 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
                 }
             }
             Assert { ref cond, expected, ref msg, target, cleanup } => {
-                use PanicInfo::*;
+                use AssertKind::*;
                 let msg = match msg {
                     BoundsCheck { ref len, ref index } => {
                         BoundsCheck { len: len.fold_with(folder), index: index.fold_with(folder) }
                     }
-                    Panic { .. }
-                    | Overflow(_)
+                    Overflow(_)
                     | OverflowNeg
                     | DivisionByZero
                     | RemainderByZero
@@ -2716,13 +2768,12 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
             }
             Assert { ref cond, ref msg, .. } => {
                 if cond.visit_with(visitor) {
-                    use PanicInfo::*;
+                    use AssertKind::*;
                     match msg {
                         BoundsCheck { ref len, ref index } => {
                             len.visit_with(visitor) || index.visit_with(visitor)
                         }
-                        Panic { .. }
-                        | Overflow(_)
+                        Overflow(_)
                         | OverflowNeg
                         | DivisionByZero
                         | RemainderByZero
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index 2f094516a35..8330bbe0834 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -533,13 +533,13 @@ macro_rules! make_mir_visitor {
             fn super_assert_message(&mut self,
                                     msg: & $($mutability)? AssertMessage<'tcx>,
                                     location: Location) {
-                use crate::mir::interpret::PanicInfo::*;
+                use crate::mir::AssertKind::*;
                 match msg {
                     BoundsCheck { len, index } => {
                         self.visit_operand(len, location);
                         self.visit_operand(index, location);
                     }
-                    Panic { .. } | Overflow(_) | OverflowNeg | DivisionByZero | RemainderByZero |
+                    Overflow(_) | OverflowNeg | DivisionByZero | RemainderByZero |
                     ResumedAfterReturn(_) | ResumedAfterPanic(_) => {
                         // Nothing to visit
                     }
diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs
index 0a4610e9e49..916c15eb1b6 100644
--- a/src/librustc_codegen_ssa/mir/block.rs
+++ b/src/librustc_codegen_ssa/mir/block.rs
@@ -11,7 +11,7 @@ use crate::MemFlags;
 
 use rustc::middle::lang_items;
 use rustc::mir;
-use rustc::mir::interpret::PanicInfo;
+use rustc::mir::AssertKind;
 use rustc::ty::layout::{self, FnAbiExt, HasTyCtxt, LayoutOf};
 use rustc::ty::{self, Instance, Ty, TypeFoldable};
 use rustc_index::vec::Idx;
@@ -378,7 +378,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         // checked operation, just a comparison with the minimum
         // value, so we have to check for the assert message.
         if !bx.check_overflow() {
-            if let PanicInfo::OverflowNeg = *msg {
+            if let AssertKind::OverflowNeg = *msg {
                 const_cond = Some(expected);
             }
         }
@@ -412,7 +412,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
         // Put together the arguments to the panic entry point.
         let (lang_item, args) = match msg {
-            PanicInfo::BoundsCheck { ref len, ref index } => {
+            AssertKind::BoundsCheck { ref len, ref index } => {
                 let len = self.codegen_operand(&mut bx, len).immediate();
                 let index = self.codegen_operand(&mut bx, index).immediate();
                 (lang_items::PanicBoundsCheckFnLangItem, vec![location, index, len])
diff --git a/src/librustc_mir/borrow_check/invalidation.rs b/src/librustc_mir/borrow_check/invalidation.rs
index 392f164d314..0bead27050c 100644
--- a/src/librustc_mir/borrow_check/invalidation.rs
+++ b/src/librustc_mir/borrow_check/invalidation.rs
@@ -153,8 +153,8 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
             }
             TerminatorKind::Assert { ref cond, expected: _, ref msg, target: _, cleanup: _ } => {
                 self.consume_operand(location, cond);
-                use rustc::mir::interpret::PanicInfo;
-                if let PanicInfo::BoundsCheck { ref len, ref index } = *msg {
+                use rustc::mir::AssertKind;
+                if let AssertKind::BoundsCheck { ref len, ref index } = *msg {
                     self.consume_operand(location, len);
                     self.consume_operand(location, index);
                 }
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 88173137bd2..941534e68fc 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -654,8 +654,8 @@ impl<'cx, 'tcx> dataflow::generic::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt
             }
             TerminatorKind::Assert { ref cond, expected: _, ref msg, target: _, cleanup: _ } => {
                 self.consume_operand(loc, (cond, span), flow_state);
-                use rustc::mir::interpret::PanicInfo;
-                if let PanicInfo::BoundsCheck { ref len, ref index } = *msg {
+                use rustc::mir::AssertKind;
+                if let AssertKind::BoundsCheck { ref len, ref index } = *msg {
                     self.consume_operand(loc, (len, span), flow_state);
                     self.consume_operand(loc, (index, span), flow_state);
                 }
diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs
index 4cbe4145589..5dab064c7b7 100644
--- a/src/librustc_mir/borrow_check/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/type_check/mod.rs
@@ -9,9 +9,9 @@ use rustc::infer::canonical::QueryRegionConstraints;
 use rustc::infer::outlives::env::RegionBoundPairs;
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin};
-use rustc::mir::interpret::PanicInfo;
 use rustc::mir::tcx::PlaceTy;
 use rustc::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
+use rustc::mir::AssertKind;
 use rustc::mir::*;
 use rustc::traits::query::type_op;
 use rustc::traits::query::type_op::custom::CustomTypeOp;
@@ -1562,7 +1562,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     span_mirbug!(self, term, "bad Assert ({:?}, not bool", cond_ty);
                 }
 
-                if let PanicInfo::BoundsCheck { ref len, ref index } = *msg {
+                if let AssertKind::BoundsCheck { ref len, ref index } = *msg {
                     if len.ty(body, tcx) != tcx.types.usize {
                         span_mirbug!(self, len, "bounds-check length non-usize {:?}", len)
                     }
diff --git a/src/librustc_mir/const_eval/error.rs b/src/librustc_mir/const_eval/error.rs
index c2db3c31f85..63ad9ec8cae 100644
--- a/src/librustc_mir/const_eval/error.rs
+++ b/src/librustc_mir/const_eval/error.rs
@@ -1,33 +1,47 @@
 use std::error::Error;
 use std::fmt;
 
+use rustc::mir::AssertKind;
+use rustc_span::Symbol;
+
 use super::InterpCx;
-use crate::interpret::{ConstEvalErr, InterpErrorInfo, Machine};
+use crate::interpret::{ConstEvalErr, InterpError, InterpErrorInfo, Machine};
+
+/// The CTFE machine has some custom error kinds.
 #[derive(Clone, Debug)]
-pub enum ConstEvalError {
+pub enum ConstEvalErrKind {
     NeedsRfc(String),
     ConstAccessesStatic,
+    AssertFailure(AssertKind<u64>),
+    Panic { msg: Symbol, line: u32, col: u32, file: Symbol },
 }
 
-impl<'tcx> Into<InterpErrorInfo<'tcx>> for ConstEvalError {
+// The errors become `MachineStop` with plain strings when being raised.
+// `ConstEvalErr` (in `librustc/mir/interpret/error.rs`) knows to
+// handle these.
+impl<'tcx> Into<InterpErrorInfo<'tcx>> for ConstEvalErrKind {
     fn into(self) -> InterpErrorInfo<'tcx> {
-        err_unsup!(Unsupported(self.to_string())).into()
+        InterpError::MachineStop(Box::new(self.to_string())).into()
     }
 }
 
-impl fmt::Display for ConstEvalError {
+impl fmt::Display for ConstEvalErrKind {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use self::ConstEvalError::*;
+        use self::ConstEvalErrKind::*;
         match *self {
             NeedsRfc(ref msg) => {
                 write!(f, "\"{}\" needs an rfc before being allowed inside constants", msg)
             }
             ConstAccessesStatic => write!(f, "constant accesses static"),
+            AssertFailure(ref msg) => write!(f, "{:?}", msg),
+            Panic { msg, line, col, file } => {
+                write!(f, "the evaluated program panicked at '{}', {}:{}:{}", msg, file, line, col)
+            }
         }
     }
 }
 
-impl Error for ConstEvalError {}
+impl Error for ConstEvalErrKind {}
 
 /// Turn an interpreter error into something to report to the user.
 /// As a side-effect, if RUSTC_CTFE_BACKTRACE is set, this prints the backtrace.
diff --git a/src/librustc_mir/const_eval/machine.rs b/src/librustc_mir/const_eval/machine.rs
index 1aed91baba6..e40436ccf0b 100644
--- a/src/librustc_mir/const_eval/machine.rs
+++ b/src/librustc_mir/const_eval/machine.rs
@@ -8,11 +8,13 @@ use std::hash::Hash;
 
 use rustc_data_structures::fx::FxHashMap;
 
+use rustc::mir::AssertMessage;
 use rustc_span::source_map::Span;
+use rustc_span::symbol::Symbol;
 
 use crate::interpret::{
-    self, snapshot, AllocId, Allocation, AssertMessage, GlobalId, ImmTy, InterpCx, InterpResult,
-    Memory, MemoryKind, OpTy, PlaceTy, Pointer, Scalar,
+    self, snapshot, AllocId, Allocation, GlobalId, ImmTy, InterpCx, InterpResult, Memory,
+    MemoryKind, OpTy, PlaceTy, Pointer, Scalar,
 };
 
 use super::error::*;
@@ -56,6 +58,32 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> {
         self.dump_place(*dest);
         return Ok(true);
     }
+
+    /// "Intercept" a function call to a panic-related function
+    /// because we have something special to do for it.
+    /// If this returns successfully (`Ok`), the function should just be evaluated normally.
+    fn hook_panic_fn(
+        &mut self,
+        span: Span,
+        instance: ty::Instance<'tcx>,
+        args: &[OpTy<'tcx>],
+    ) -> InterpResult<'tcx> {
+        let def_id = instance.def_id();
+        if Some(def_id) == self.tcx.lang_items().panic_fn()
+            || Some(def_id) == self.tcx.lang_items().begin_panic_fn()
+        {
+            // &'static str
+            assert!(args.len() == 1);
+
+            let msg_place = self.deref_operand(args[0])?;
+            let msg = Symbol::intern(self.read_str(msg_place)?);
+            let span = self.find_closest_untracked_caller_location().unwrap_or(span);
+            let (file, line, col) = self.location_triple_for_span(span);
+            Err(ConstEvalErrKind::Panic { msg, file, line, col }.into())
+        } else {
+            Ok(())
+        }
+    }
 }
 
 /// Number of steps until the detector even starts doing anything.
@@ -198,13 +226,11 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
                 }
             } else {
                 // Some functions we support even if they are non-const -- but avoid testing
-                // that for const fn!  We certainly do *not* want to actually call the fn
+                // that for const fn!
+                ecx.hook_panic_fn(span, instance, args)?;
+                // We certainly do *not* want to actually call the fn
                 // though, so be sure we return here.
-                return if ecx.hook_panic_fn(span, instance, args)? {
-                    Ok(None)
-                } else {
-                    throw_unsup_format!("calling non-const function `{}`", instance)
-                };
+                throw_unsup_format!("calling non-const function `{}`", instance)
             }
         }
         // This is a const fn. Call it.
@@ -212,7 +238,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
             Ok(body) => *body,
             Err(err) => {
                 if let err_unsup!(NoMirFor(ref path)) = err.kind {
-                    return Err(ConstEvalError::NeedsRfc(format!(
+                    return Err(ConstEvalErrKind::NeedsRfc(format!(
                         "calling extern function `{}`",
                         path
                     ))
@@ -246,7 +272,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
         }
         // An intrinsic that we do not support
         let intrinsic_name = ecx.tcx.item_name(instance.def_id());
-        Err(ConstEvalError::NeedsRfc(format!("calling intrinsic `{}`", intrinsic_name)).into())
+        Err(ConstEvalErrKind::NeedsRfc(format!("calling intrinsic `{}`", intrinsic_name)).into())
     }
 
     fn assert_panic(
@@ -255,8 +281,9 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
         msg: &AssertMessage<'tcx>,
         _unwind: Option<mir::BasicBlock>,
     ) -> InterpResult<'tcx> {
-        use rustc::mir::interpret::PanicInfo::*;
-        Err(match msg {
+        use rustc::mir::AssertKind::*;
+        // Convert `AssertKind<Operand>` to `AssertKind<u64>`.
+        let err = match msg {
             BoundsCheck { ref len, ref index } => {
                 let len = ecx
                     .read_immediate(ecx.eval_operand(len, None)?)
@@ -268,21 +295,20 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
                     .expect("can't eval index")
                     .to_scalar()?
                     .to_machine_usize(&*ecx)?;
-                err_panic!(BoundsCheck { len, index })
+                BoundsCheck { len, index }
             }
-            Overflow(op) => err_panic!(Overflow(*op)),
-            OverflowNeg => err_panic!(OverflowNeg),
-            DivisionByZero => err_panic!(DivisionByZero),
-            RemainderByZero => err_panic!(RemainderByZero),
-            ResumedAfterReturn(generator_kind) => err_panic!(ResumedAfterReturn(*generator_kind)),
-            ResumedAfterPanic(generator_kind) => err_panic!(ResumedAfterPanic(*generator_kind)),
-            Panic { .. } => bug!("`Panic` variant cannot occur in MIR"),
-        }
-        .into())
+            Overflow(op) => Overflow(*op),
+            OverflowNeg => OverflowNeg,
+            DivisionByZero => DivisionByZero,
+            RemainderByZero => RemainderByZero,
+            ResumedAfterReturn(generator_kind) => ResumedAfterReturn(*generator_kind),
+            ResumedAfterPanic(generator_kind) => ResumedAfterPanic(*generator_kind),
+        };
+        Err(ConstEvalErrKind::AssertFailure(err).into())
     }
 
     fn ptr_to_int(_mem: &Memory<'mir, 'tcx, Self>, _ptr: Pointer) -> InterpResult<'tcx, u64> {
-        Err(ConstEvalError::NeedsRfc("pointer-to-integer cast".to_string()).into())
+        Err(ConstEvalErrKind::NeedsRfc("pointer-to-integer cast".to_string()).into())
     }
 
     fn binary_ptr_op(
@@ -291,7 +317,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
         _left: ImmTy<'tcx>,
         _right: ImmTy<'tcx>,
     ) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> {
-        Err(ConstEvalError::NeedsRfc("pointer arithmetic or comparison".to_string()).into())
+        Err(ConstEvalErrKind::NeedsRfc("pointer arithmetic or comparison".to_string()).into())
     }
 
     fn find_foreign_static(
@@ -321,7 +347,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
         _ecx: &mut InterpCx<'mir, 'tcx, Self>,
         _dest: PlaceTy<'tcx>,
     ) -> InterpResult<'tcx> {
-        Err(ConstEvalError::NeedsRfc("heap allocations via `box` keyword".to_string()).into())
+        Err(ConstEvalErrKind::NeedsRfc("heap allocations via `box` keyword".to_string()).into())
     }
 
     fn before_terminator(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
@@ -355,7 +381,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
         if memory_extra.can_access_statics {
             Ok(())
         } else {
-            Err(ConstEvalError::ConstAccessesStatic.into())
+            Err(ConstEvalErrKind::ConstAccessesStatic.into())
         }
     }
 }
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index f85da760ada..a83b5412790 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -376,32 +376,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         Ok(true)
     }
 
-    /// "Intercept" a function call to a panic-related function
-    /// because we have something special to do for it.
-    /// Returns `true` if an intercept happened.
-    pub fn hook_panic_fn(
-        &mut self,
-        span: Span,
-        instance: ty::Instance<'tcx>,
-        args: &[OpTy<'tcx, M::PointerTag>],
-    ) -> InterpResult<'tcx, bool> {
-        let def_id = instance.def_id();
-        if Some(def_id) == self.tcx.lang_items().panic_fn()
-            || Some(def_id) == self.tcx.lang_items().begin_panic_fn()
-        {
-            // &'static str
-            assert!(args.len() == 1);
-
-            let msg_place = self.deref_operand(args[0])?;
-            let msg = Symbol::intern(self.read_str(msg_place)?);
-            let span = self.find_closest_untracked_caller_location().unwrap_or(span);
-            let (file, line, col) = self.location_triple_for_span(span);
-            throw_panic!(Panic { msg, file, line, col })
-        } else {
-            return Ok(false);
-        }
-    }
-
     pub fn exact_div(
         &mut self,
         a: ImmTy<'tcx, M::PointerTag>,
diff --git a/src/librustc_mir/interpret/intrinsics/caller_location.rs b/src/librustc_mir/interpret/intrinsics/caller_location.rs
index 0525108d2d1..566601f0cae 100644
--- a/src/librustc_mir/interpret/intrinsics/caller_location.rs
+++ b/src/librustc_mir/interpret/intrinsics/caller_location.rs
@@ -54,12 +54,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         location
     }
 
-    pub fn alloc_caller_location_for_span(&mut self, span: Span) -> MPlaceTy<'tcx, M::PointerTag> {
-        let (file, line, column) = self.location_triple_for_span(span);
-        self.alloc_caller_location(file, line, column)
-    }
-
-    pub(super) fn location_triple_for_span(&self, span: Span) -> (Symbol, u32, u32) {
+    crate fn location_triple_for_span(&self, span: Span) -> (Symbol, u32, u32) {
         let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
         let caller = self.tcx.sess.source_map().lookup_char_pos(topmost.lo());
         (
@@ -68,4 +63,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             caller.col_display as u32 + 1,
         )
     }
+
+    pub fn alloc_caller_location_for_span(&mut self, span: Span) -> MPlaceTy<'tcx, M::PointerTag> {
+        let (file, line, column) = self.location_triple_for_span(span);
+        self.alloc_caller_location(file, line, column)
+    }
 }
diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs
index 3309e9b9b62..5291000d10b 100644
--- a/src/librustc_mir/interpret/machine.rs
+++ b/src/librustc_mir/interpret/machine.rs
@@ -11,8 +11,8 @@ use rustc_hir::def_id::DefId;
 use rustc_span::Span;
 
 use super::{
-    AllocId, Allocation, AllocationExtra, AssertMessage, Frame, ImmTy, InterpCx, InterpResult,
-    Memory, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Scalar,
+    AllocId, Allocation, AllocationExtra, Frame, ImmTy, InterpCx, InterpResult, Memory, MemoryKind,
+    OpTy, Operand, PlaceTy, Pointer, Scalar,
 };
 
 /// Data returned by Machine::stack_pop,
@@ -171,7 +171,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
     fn assert_panic(
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
         span: Span,
-        msg: &AssertMessage<'tcx>,
+        msg: &mir::AssertMessage<'tcx>,
         unwind: Option<mir::BasicBlock>,
     ) -> InterpResult<'tcx>;
 
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index a7da4f7c164..5729cda64f7 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -4,13 +4,13 @@
 use std::borrow::Cow;
 use std::cell::Cell;
 
-use rustc::mir::interpret::{InterpResult, PanicInfo, Scalar};
+use rustc::mir::interpret::{InterpError, InterpResult, Scalar};
 use rustc::mir::visit::{
     MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor,
 };
 use rustc::mir::{
-    read_only, AggregateKind, BasicBlock, BinOp, Body, BodyAndCache, ClearCrossCrate, Constant,
-    Local, LocalDecl, LocalKind, Location, Operand, Place, ReadOnlyBodyAndCache, Rvalue,
+    read_only, AggregateKind, AssertKind, BasicBlock, BinOp, Body, BodyAndCache, ClearCrossCrate,
+    Constant, Local, LocalDecl, LocalKind, Location, Operand, Place, ReadOnlyBodyAndCache, Rvalue,
     SourceInfo, SourceScope, SourceScopeData, Statement, StatementKind, Terminator, TerminatorKind,
     UnOp, RETURN_PLACE,
 };
@@ -25,7 +25,7 @@ use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_hir::HirId;
 use rustc_index::vec::IndexVec;
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::Span;
 use syntax::ast::Mutability;
 
 use crate::const_eval::error_to_const_error;
@@ -198,7 +198,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
     fn assert_panic(
         _ecx: &mut InterpCx<'mir, 'tcx, Self>,
         _span: Span,
-        _msg: &rustc::mir::interpret::AssertMessage<'tcx>,
+        _msg: &rustc::mir::AssertMessage<'tcx>,
         _unwind: Option<rustc::mir::BasicBlock>,
     ) -> InterpResult<'tcx> {
         bug!("panics terminators are not evaluated in ConstProp");
@@ -410,15 +410,10 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         }
     }
 
-    fn use_ecx<F, T>(&mut self, source_info: SourceInfo, f: F) -> Option<T>
+    fn use_ecx<F, T>(&mut self, f: F) -> Option<T>
     where
         F: FnOnce(&mut Self) -> InterpResult<'tcx, T>,
     {
-        self.ecx.tcx.span = source_info.span;
-        // FIXME(eddyb) move this to the `Panic(_)` error case, so that
-        // `f(self)` is always called, and that the only difference when the
-        // scope's `local_data` is missing, is that the lint isn't emitted.
-        let lint_root = self.lint_root(source_info)?;
         let r = match f(self) {
             Ok(val) => Some(val),
             Err(error) => {
@@ -447,20 +442,10 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                     | ResourceExhaustion(_) => {
                         // Ignore these errors.
                     }
-                    Panic(_) => {
-                        let diagnostic = error_to_const_error(&self.ecx, error);
-                        diagnostic.report_as_lint(
-                            self.ecx.tcx,
-                            "this expression will panic at runtime",
-                            lint_root,
-                            None,
-                        );
-                    }
                 }
                 None
             }
         };
-        self.ecx.tcx.span = DUMMY_SP;
         r
     }
 
@@ -504,37 +489,49 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         }
     }
 
-    fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option<OpTy<'tcx>> {
+    fn eval_place(&mut self, place: &Place<'tcx>) -> Option<OpTy<'tcx>> {
         trace!("eval_place(place={:?})", place);
-        self.use_ecx(source_info, |this| this.ecx.eval_place_to_op(place, None))
+        self.use_ecx(|this| this.ecx.eval_place_to_op(place, None))
     }
 
     fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option<OpTy<'tcx>> {
         match *op {
             Operand::Constant(ref c) => self.eval_constant(c, source_info),
-            Operand::Move(ref place) | Operand::Copy(ref place) => {
-                self.eval_place(place, source_info)
-            }
+            Operand::Move(ref place) | Operand::Copy(ref place) => self.eval_place(place),
         }
     }
 
+    fn report_panic_as_lint(&self, source_info: SourceInfo, panic: AssertKind<u64>) -> Option<()> {
+        // Somewhat convoluted way to re-use the CTFE error reporting code.
+        let lint_root = self.lint_root(source_info)?;
+        let error = InterpError::MachineStop(Box::new(format!("{:?}", panic)));
+        let mut diagnostic = error_to_const_error(&self.ecx, error.into());
+        diagnostic.span = source_info.span; // fix the span
+        diagnostic.report_as_lint(
+            self.tcx.at(source_info.span),
+            "this expression will panic at runtime",
+            lint_root,
+            None,
+        );
+        None
+    }
+
     fn check_unary_op(
         &mut self,
         op: UnOp,
         arg: &Operand<'tcx>,
         source_info: SourceInfo,
     ) -> Option<()> {
-        self.use_ecx(source_info, |this| {
+        if self.use_ecx(|this| {
             let val = this.ecx.read_immediate(this.ecx.eval_operand(arg, None)?)?;
             let (_res, overflow, _ty) = this.ecx.overflowing_unary_op(op, val)?;
-
-            if overflow {
-                assert_eq!(op, UnOp::Neg, "Neg is the only UnOp that can overflow");
-                throw_panic!(OverflowNeg);
-            }
-
-            Ok(())
-        })?;
+            Ok(overflow)
+        })? {
+            // `AssertKind` only has an `OverflowNeg` variant, so make sure that is
+            // appropriate to use.
+            assert_eq!(op, UnOp::Neg, "Neg is the only UnOp that can overflow");
+            self.report_panic_as_lint(source_info, AssertKind::OverflowNeg)?;
+        }
 
         Some(())
     }
@@ -546,11 +543,10 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         right: &Operand<'tcx>,
         source_info: SourceInfo,
         place_layout: TyLayout<'tcx>,
-        overflow_check: bool,
     ) -> Option<()> {
-        let r = self.use_ecx(source_info, |this| {
-            this.ecx.read_immediate(this.ecx.eval_operand(right, None)?)
-        })?;
+        let r =
+            self.use_ecx(|this| this.ecx.read_immediate(this.ecx.eval_operand(right, None)?))?;
+        // Check for exceeding shifts *even if* we cannot evaluate the LHS.
         if op == BinOp::Shr || op == BinOp::Shl {
             let left_bits = place_layout.size.bits();
             let right_size = r.layout.size;
@@ -570,21 +566,13 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
             }
         }
 
-        // If overflow checking is enabled (like in debug mode by default),
-        // then we'll already catch overflow when we evaluate the `Assert` statement
-        // in MIR. However, if overflow checking is disabled, then there won't be any
-        // `Assert` statement and so we have to do additional checking here.
-        if !overflow_check {
-            self.use_ecx(source_info, |this| {
-                let l = this.ecx.read_immediate(this.ecx.eval_operand(left, None)?)?;
-                let (_res, overflow, _ty) = this.ecx.overflowing_binary_op(op, l, r)?;
-
-                if overflow {
-                    throw_panic!(Overflow(op));
-                }
-
-                Ok(())
-            })?;
+        // The remaining operators are handled through `overflowing_binary_op`.
+        if self.use_ecx(|this| {
+            let l = this.ecx.read_immediate(this.ecx.eval_operand(left, None)?)?;
+            let (_res, overflow, _ty) = this.ecx.overflowing_binary_op(op, l, r)?;
+            Ok(overflow)
+        })? {
+            self.report_panic_as_lint(source_info, AssertKind::Overflow(op))?;
         }
 
         Some(())
@@ -617,9 +605,9 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         //   2. Working around bugs in other parts of the compiler
         //        - In this case, we'll return `None` from this function to stop evaluation.
         match rvalue {
-            // Additional checking: if overflow checks are disabled (which is usually the case in
-            // release mode), then we need to do additional checking here to give lints to the user
-            // if an overflow would occur.
+            // Additional checking: give lints to the user if an overflow would occur.
+            // If `overflow_check` is set, running const-prop on the `Assert` terminators
+            // will already generate the appropriate messages.
             Rvalue::UnaryOp(op, arg) if !overflow_check => {
                 trace!("checking UnaryOp(op = {:?}, arg = {:?})", op, arg);
                 self.check_unary_op(*op, arg, source_info)?;
@@ -627,9 +615,11 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
 
             // Additional checking: check for overflows on integer binary operations and report
             // them to the user as lints.
-            Rvalue::BinaryOp(op, left, right) => {
+            // If `overflow_check` is set, running const-prop on the `Assert` terminators
+            // will already generate the appropriate messages.
+            Rvalue::BinaryOp(op, left, right) if !overflow_check => {
                 trace!("checking BinaryOp(op = {:?}, left = {:?}, right = {:?})", op, left, right);
-                self.check_binary_op(*op, left, right, source_info, place_layout, overflow_check)?;
+                self.check_binary_op(*op, left, right, source_info, place_layout)?;
             }
 
             // Do not try creating references (#67862)
@@ -642,7 +632,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
             _ => {}
         }
 
-        self.use_ecx(source_info, |this| {
+        self.use_ecx(|this| {
             trace!("calling eval_rvalue_into_place(rvalue = {:?}, place = {:?})", rvalue, place);
             this.ecx.eval_rvalue_into_place(rvalue, place)?;
             Ok(())
@@ -675,7 +665,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         }
 
         // FIXME> figure out what tho do when try_read_immediate fails
-        let imm = self.use_ecx(source_info, |this| this.ecx.try_read_immediate(value));
+        let imm = self.use_ecx(|this| this.ecx.try_read_immediate(value));
 
         if let Some(Ok(imm)) = imm {
             match *imm {
@@ -698,7 +688,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                     if let ty::Tuple(substs) = ty {
                         // Only do it if tuple is also a pair with two scalars
                         if substs.len() == 2 {
-                            let opt_ty1_ty2 = self.use_ecx(source_info, |this| {
+                            let opt_ty1_ty2 = self.use_ecx(|this| {
                                 let ty1 = substs[0].expect_ty();
                                 let ty2 = substs[1].expect_ty();
                                 let ty_is_scalar = |ty| {
@@ -920,11 +910,11 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
                             span,
                             |lint| {
                                 let msg = match msg {
-                                    PanicInfo::Overflow(_)
-                                    | PanicInfo::OverflowNeg
-                                    | PanicInfo::DivisionByZero
-                                    | PanicInfo::RemainderByZero => msg.description().to_owned(),
-                                    PanicInfo::BoundsCheck { ref len, ref index } => {
+                                    AssertKind::Overflow(_)
+                                    | AssertKind::OverflowNeg
+                                    | AssertKind::DivisionByZero
+                                    | AssertKind::RemainderByZero => msg.description().to_owned(),
+                                    AssertKind::BoundsCheck { ref len, ref index } => {
                                         let len = self
                                             .eval_operand(len, source_info)
                                             .expect("len must be const");
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index a6fc6573178..d5d9a8c83cd 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -1022,7 +1022,7 @@ fn create_generator_resume_function<'tcx>(
 
     let mut cases = create_cases(body, &transform, Operation::Resume);
 
-    use rustc::mir::interpret::PanicInfo::{ResumedAfterPanic, ResumedAfterReturn};
+    use rustc::mir::AssertKind::{ResumedAfterPanic, ResumedAfterReturn};
 
     // Jump to the entry point on the unresumed
     cases.insert(0, (UNRESUMED, BasicBlock::new(0)));
diff --git a/src/librustc_mir_build/build/expr/as_place.rs b/src/librustc_mir_build/build/expr/as_place.rs
index 907300d45aa..d77cc49c94f 100644
--- a/src/librustc_mir_build/build/expr/as_place.rs
+++ b/src/librustc_mir_build/build/expr/as_place.rs
@@ -5,7 +5,7 @@ use crate::build::ForGuard::{OutsideGuard, RefWithinGuard};
 use crate::build::{BlockAnd, BlockAndExtension, Builder};
 use crate::hair::*;
 use rustc::middle::region;
-use rustc::mir::interpret::PanicInfo::BoundsCheck;
+use rustc::mir::AssertKind::BoundsCheck;
 use rustc::mir::*;
 use rustc::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, Variance};
 use rustc_span::Span;
diff --git a/src/librustc_mir_build/build/expr/as_rvalue.rs b/src/librustc_mir_build/build/expr/as_rvalue.rs
index 6f5c5f0dd4c..dc97f321a36 100644
--- a/src/librustc_mir_build/build/expr/as_rvalue.rs
+++ b/src/librustc_mir_build/build/expr/as_rvalue.rs
@@ -6,7 +6,7 @@ use crate::build::expr::category::{Category, RvalueFunc};
 use crate::build::{BlockAnd, BlockAndExtension, Builder};
 use crate::hair::*;
 use rustc::middle::region;
-use rustc::mir::interpret::PanicInfo;
+use rustc::mir::AssertKind;
 use rustc::mir::*;
 use rustc::ty::{self, Ty, UpvarSubsts};
 use rustc_span::Span;
@@ -86,7 +86,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         block,
                         Operand::Move(is_min),
                         false,
-                        PanicInfo::OverflowNeg,
+                        AssertKind::OverflowNeg,
                         expr_span,
                     );
                 }
@@ -294,7 +294,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             let val = tcx.mk_place_field(result_value.clone(), val_fld, ty);
             let of = tcx.mk_place_field(result_value, of_fld, bool_ty);
 
-            let err = PanicInfo::Overflow(op);
+            let err = AssertKind::Overflow(op);
 
             block = self.assert(block, Operand::Move(of), false, err, span);
 
@@ -305,11 +305,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 // and 2. there are two possible failure cases, divide-by-zero and overflow.
 
                 let zero_err = if op == BinOp::Div {
-                    PanicInfo::DivisionByZero
+                    AssertKind::DivisionByZero
                 } else {
-                    PanicInfo::RemainderByZero
+                    AssertKind::RemainderByZero
                 };
-                let overflow_err = PanicInfo::Overflow(op);
+                let overflow_err = AssertKind::Overflow(op);
 
                 // Check for / 0
                 let is_zero = self.temp(bool_ty, span);