about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/mir/interpret/error.rs337
-rw-r--r--src/librustc/mir/mod.rs31
-rw-r--r--src/librustc/mir/visit.rs15
-rw-r--r--src/librustc_codegen_ssa/mir/block.rs8
-rw-r--r--src/librustc_mir/borrow_check/mod.rs4
-rw-r--r--src/librustc_mir/borrow_check/nll/invalidation.rs4
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs4
-rw-r--r--src/librustc_mir/build/expr/as_place.rs6
-rw-r--r--src/librustc_mir/build/expr/as_rvalue.rs13
-rw-r--r--src/librustc_mir/interpret/terminator.rs35
-rw-r--r--src/librustc_mir/transform/const_prop.rs20
-rw-r--r--src/librustc_mir/transform/generator.rs2
12 files changed, 241 insertions, 238 deletions
diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs
index 6ab07c9679e..5309d5b039e 100644
--- a/src/librustc/mir/interpret/error.rs
+++ b/src/librustc/mir/interpret/error.rs
@@ -47,7 +47,7 @@ pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ErrorHandled>;
 #[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
 pub struct ConstEvalErr<'tcx> {
     pub span: Span,
-    pub error: crate::mir::interpret::InterpError<'tcx, u64>,
+    pub error: crate::mir::interpret::InterpError<'tcx>,
     pub stacktrace: Vec<FrameInfo<'tcx>>,
 }
 
@@ -185,11 +185,18 @@ pub fn struct_error<'tcx>(tcx: TyCtxtAt<'tcx>, msg: &str) -> DiagnosticBuilder<'
 /// macro for this.
 #[derive(Debug, Clone)]
 pub struct InterpErrorInfo<'tcx> {
-    pub kind: InterpError<'tcx, u64>,
+    pub kind: InterpError<'tcx>,
     backtrace: Option<Box<Backtrace>>,
 }
 
-impl<'tcx> InterpErrorInfo<'tcx> {
+
+impl fmt::Display for InterpErrorInfo<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{}", self.kind)
+    }
+}
+
+impl InterpErrorInfo<'_> {
     pub fn print_backtrace(&mut self) {
         if let Some(ref mut backtrace) = self.backtrace {
             print_backtrace(&mut *backtrace);
@@ -202,8 +209,8 @@ fn print_backtrace(backtrace: &mut Backtrace) {
     eprintln!("\n\nAn error occurred in miri:\n{:?}", backtrace);
 }
 
-impl<'tcx> From<InterpError<'tcx, u64>> for InterpErrorInfo<'tcx> {
-    fn from(kind: InterpError<'tcx, u64>) -> Self {
+impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
+    fn from(kind: InterpError<'tcx>) -> Self {
         let backtrace = match env::var("RUST_CTFE_BACKTRACE") {
             // Matching `RUST_BACKTRACE` -- we treat "0" the same as "not present".
             Ok(ref val) if val != "0" => {
@@ -226,8 +233,6 @@ impl<'tcx> From<InterpError<'tcx, u64>> for InterpErrorInfo<'tcx> {
     }
 }
 
-pub type AssertMessage<'tcx> = InterpError<'tcx, mir::Operand<'tcx>>;
-
 #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
 pub enum PanicMessage<O> {
     Panic {
@@ -244,10 +249,68 @@ pub enum PanicMessage<O> {
     OverflowNeg,
     DivisionByZero,
     RemainderByZero,
+    GeneratorResumedAfterReturn,
+    GeneratorResumedAfterPanic,
+}
+
+/// Type for MIR `Assert` terminator error messages.
+pub type AssertMessage<'tcx> = PanicMessage<mir::Operand<'tcx>>;
+
+impl<O> PanicMessage<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 PanicMessage::*;
+        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",
+            GeneratorResumedAfterReturn =>
+                "generator resumed after completion",
+            GeneratorResumedAfterPanic =>
+                "generator resumed after panicking",
+            Panic { .. } | BoundsCheck { .. } =>
+                bug!("Unexpected PanicMessage"),
+        }
+    }
+}
+
+impl<O: fmt::Debug> fmt::Debug for PanicMessage<O> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use PanicMessage::*;
+        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()),
+        }
+    }
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
-pub enum InterpError<'tcx, O> {
+pub enum InterpError<'tcx> {
     /// This variant is used by machines to signal their own errors that do not
     /// match an existing variant.
     MachineError(String),
@@ -311,7 +374,7 @@ pub enum InterpError<'tcx, O> {
     HeapAllocZeroBytes,
     HeapAllocNonPowerOfTwoAlignment(u64),
     Unreachable,
-    Panic(PanicMessage<O>),
+    Panic(PanicMessage<u64>),
     ReadFromReturnPointer,
     PathNotFound(Vec<String>),
     UnimplementedTraitSelection,
@@ -322,173 +385,21 @@ pub enum InterpError<'tcx, O> {
     /// Cannot compute this constant because it depends on another one
     /// which already produced an error
     ReferencedConstant,
-    GeneratorResumedAfterReturn,
-    GeneratorResumedAfterPanic,
     InfiniteLoop,
 }
 
 pub type InterpResult<'tcx, T = ()> = Result<T, InterpErrorInfo<'tcx>>;
 
-impl<'tcx, O> InterpError<'tcx, O> {
-    pub fn description(&self) -> &str {
-        use self::InterpError::*;
-        match *self {
-            MachineError(ref inner) => inner,
-            Exit(..) =>
-                "exited",
-            FunctionAbiMismatch(..) | FunctionArgMismatch(..) | FunctionRetMismatch(..)
-            | FunctionArgCountMismatch =>
-                "tried to call a function through a function pointer of incompatible type",
-            InvalidMemoryAccess =>
-                "tried to access memory through an invalid pointer",
-            DanglingPointerDeref =>
-                "dangling pointer was dereferenced",
-            DoubleFree =>
-                "tried to deallocate dangling pointer",
-            InvalidFunctionPointer =>
-                "tried to use a function pointer after offsetting it",
-            InvalidBool =>
-                "invalid boolean value read",
-            InvalidDiscriminant(..) =>
-                "invalid enum discriminant value read",
-            PointerOutOfBounds { .. } =>
-                "pointer offset outside bounds of allocation",
-            InvalidNullPointerUsage =>
-                "invalid use of NULL pointer",
-            ValidationFailure(..) =>
-                "type validation failed",
-            ReadPointerAsBytes =>
-                "a raw memory access tried to access part of a pointer value as raw bytes",
-            ReadBytesAsPointer =>
-                "a memory access tried to interpret some bytes as a pointer",
-            ReadForeignStatic =>
-                "tried to read from foreign (extern) static",
-            InvalidPointerMath =>
-                "attempted to do invalid arithmetic on pointers that would leak base addresses, \
-                e.g., comparing pointers into different allocations",
-            ReadUndefBytes(_) =>
-                "attempted to read undefined bytes",
-            DeadLocal =>
-                "tried to access a dead local variable",
-            InvalidBoolOp(_) =>
-                "invalid boolean operation",
-            Unimplemented(ref msg) => msg,
-            DerefFunctionPointer =>
-                "tried to dereference a function pointer",
-            ExecuteMemory =>
-                "tried to treat a memory pointer as a function pointer",
-            Intrinsic(..) =>
-                "intrinsic failed",
-            NoMirFor(..) =>
-                "mir not found",
-            InvalidChar(..) =>
-                "tried to interpret an invalid 32-bit value as a char",
-            StackFrameLimitReached =>
-                "reached the configured maximum number of stack frames",
-            OutOfTls =>
-                "reached the maximum number of representable TLS keys",
-            TlsOutOfBounds =>
-                "accessed an invalid (unallocated) TLS key",
-            AbiViolation(ref msg) => msg,
-            AlignmentCheckFailed{..} =>
-                "tried to execute a misaligned read or write",
-            CalledClosureAsFunction =>
-                "tried to call a closure through a function pointer",
-            VtableForArgumentlessMethod =>
-                "tried to call a vtable function without arguments",
-            ModifiedConstantMemory =>
-                "tried to modify constant memory",
-            ModifiedStatic =>
-                "tried to modify a static's initial value from another static's initializer",
-            AssumptionNotHeld =>
-                "`assume` argument was false",
-            InlineAsm =>
-                "miri does not support inline assembly",
-            TypeNotPrimitive(_) =>
-                "expected primitive type, got nonprimitive",
-            ReallocatedWrongMemoryKind(_, _) =>
-                "tried to reallocate memory from one kind to another",
-            DeallocatedWrongMemoryKind(_, _) =>
-                "tried to deallocate memory of the wrong kind",
-            ReallocateNonBasePtr =>
-                "tried to reallocate with a pointer not to the beginning of an existing object",
-            DeallocateNonBasePtr =>
-                "tried to deallocate with a pointer not to the beginning of an existing object",
-            IncorrectAllocationInformation(..) =>
-                "tried to deallocate or reallocate using incorrect alignment or size",
-            Layout(_) =>
-                "rustc layout computation failed",
-            UnterminatedCString(_) =>
-                "attempted to get length of a null terminated string, but no null found before end \
-                of allocation",
-            HeapAllocZeroBytes =>
-                "tried to re-, de- or allocate zero bytes on the heap",
-            HeapAllocNonPowerOfTwoAlignment(_) =>
-                "tried to re-, de-, or allocate heap memory with alignment that is not a power of \
-                two",
-            Unreachable =>
-                "entered unreachable code",
-            Panic(PanicMessage::Panic{..}) =>
-                "the evaluated program panicked",
-            Panic(PanicMessage::BoundsCheck{..}) =>
-                "array index out of bounds",
-            Panic(PanicMessage::Overflow(mir::BinOp::Add)) =>
-                "attempt to add with overflow",
-            Panic(PanicMessage::Overflow(mir::BinOp::Sub)) =>
-                "attempt to subtract with overflow",
-            Panic(PanicMessage::Overflow(mir::BinOp::Mul)) =>
-                "attempt to multiply with overflow",
-            Panic(PanicMessage::Overflow(mir::BinOp::Div)) =>
-                "attempt to divide with overflow",
-            Panic(PanicMessage::Overflow(mir::BinOp::Rem)) =>
-                "attempt to calculate the remainder with overflow",
-            Panic(PanicMessage::OverflowNeg) =>
-                "attempt to negate with overflow",
-            Panic(PanicMessage::Overflow(mir::BinOp::Shr)) =>
-                "attempt to shift right with overflow",
-            Panic(PanicMessage::Overflow(mir::BinOp::Shl)) =>
-                "attempt to shift left with overflow",
-            Panic(PanicMessage::Overflow(op)) =>
-                bug!("{:?} cannot overflow", op),
-            Panic(PanicMessage::DivisionByZero) =>
-                "attempt to divide by zero",
-            Panic(PanicMessage::RemainderByZero) =>
-                "attempt to calculate the remainder with a divisor of zero",
-            ReadFromReturnPointer =>
-                "tried to read from the return pointer",
-            PathNotFound(_) =>
-                "a path could not be resolved, maybe the crate is not loaded",
-            UnimplementedTraitSelection =>
-                "there were unresolved type arguments during trait selection",
-            TypeckError =>
-                "encountered constants with type errors, stopping evaluation",
-            TooGeneric =>
-                "encountered overly generic constant",
-            ReferencedConstant =>
-                "referenced constant has errors",
-            GeneratorResumedAfterReturn => "generator resumed after completion",
-            GeneratorResumedAfterPanic => "generator resumed after panicking",
-            InfiniteLoop =>
-                "duplicate interpreter state observed here, const evaluation will never terminate",
-        }
-    }
-}
-
-impl<'tcx> fmt::Display for InterpErrorInfo<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{}", self.kind)
-    }
-}
-
-impl<'tcx> fmt::Display for InterpError<'tcx, u64> {
+impl fmt::Display for InterpError<'_> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        // Forward `Display` to `Debug`
         write!(f, "{:?}", self)
     }
 }
 
-impl<'tcx, O: fmt::Debug> fmt::Debug for InterpError<'tcx, O> {
+impl fmt::Debug for InterpError<'_> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use self::InterpError::*;
+        use InterpError::*;
         match *self {
             PointerOutOfBounds { ptr, msg, allocation_size } => {
                 write!(f, "{} failed: pointer must be in-bounds at offset {}, \
@@ -516,8 +427,6 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for InterpError<'tcx, O> {
                 write!(f, "tried to reallocate memory from {} to {}", old, new),
             DeallocatedWrongMemoryKind(ref old, ref new) =>
                 write!(f, "tried to deallocate {} memory but gave {} as the kind", old, new),
-            Intrinsic(ref err) =>
-                write!(f, "{}", err),
             InvalidChar(c) =>
                 write!(f, "tried to interpret an invalid 32-bit value as a char: {}", c),
             AlignmentCheckFailed { required, has } =>
@@ -529,21 +438,101 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for InterpError<'tcx, O> {
                 write!(f, "rustc layout computation failed: {:?}", err),
             PathNotFound(ref path) =>
                 write!(f, "Cannot find path {:?}", path),
-            MachineError(ref inner) =>
-                write!(f, "{}", inner),
             IncorrectAllocationInformation(size, size2, align, align2) =>
                 write!(f, "incorrect alloc info: expected size {} and align {}, \
                            got size {} and align {}",
                     size.bytes(), align.bytes(), size2.bytes(), align2.bytes()),
-            Panic(PanicMessage::Panic { ref msg, line, col, ref file }) =>
-                write!(f, "the evaluated program panicked at '{}', {}:{}:{}", msg, file, line, col),
-            Panic(PanicMessage::BoundsCheck { ref len, ref index }) =>
-                write!(f, "index out of bounds: the len is {:?} but the index is {:?}", len, index),
             InvalidDiscriminant(val) =>
                 write!(f, "encountered invalid enum discriminant {}", val),
             Exit(code) =>
                 write!(f, "exited with status code {}", code),
-            _ => write!(f, "{}", self.description()),
+            InvalidMemoryAccess =>
+                write!(f, "tried to access memory through an invalid pointer"),
+            DanglingPointerDeref =>
+                write!(f, "dangling pointer was dereferenced"),
+            DoubleFree =>
+                write!(f, "tried to deallocate dangling pointer"),
+            InvalidFunctionPointer =>
+                write!(f, "tried to use a function pointer after offsetting it"),
+            InvalidBool =>
+                write!(f, "invalid boolean value read"),
+            InvalidNullPointerUsage =>
+                write!(f, "invalid use of NULL pointer"),
+            ReadPointerAsBytes =>
+                write!(f, "a raw memory access tried to access part of a pointer value as raw \
+                    bytes"),
+            ReadBytesAsPointer =>
+                write!(f, "a memory access tried to interpret some bytes as a pointer"),
+            ReadForeignStatic =>
+                write!(f, "tried to read from foreign (extern) static"),
+            InvalidPointerMath =>
+                write!(f, "attempted to do invalid arithmetic on pointers that would leak base \
+                    addresses, e.g., comparing pointers into different allocations"),
+            DeadLocal =>
+                write!(f, "tried to access a dead local variable"),
+            DerefFunctionPointer =>
+                write!(f, "tried to dereference a function pointer"),
+            ExecuteMemory =>
+                write!(f, "tried to treat a memory pointer as a function pointer"),
+            StackFrameLimitReached =>
+                write!(f, "reached the configured maximum number of stack frames"),
+            OutOfTls =>
+                write!(f, "reached the maximum number of representable TLS keys"),
+            TlsOutOfBounds =>
+                write!(f, "accessed an invalid (unallocated) TLS key"),
+            CalledClosureAsFunction =>
+                write!(f, "tried to call a closure through a function pointer"),
+            VtableForArgumentlessMethod =>
+                write!(f, "tried to call a vtable function without arguments"),
+            ModifiedConstantMemory =>
+                write!(f, "tried to modify constant memory"),
+            ModifiedStatic =>
+                write!(f, "tried to modify a static's initial value from another static's \
+                    initializer"),
+            AssumptionNotHeld =>
+                write!(f, "`assume` argument was false"),
+            InlineAsm =>
+                write!(f, "miri does not support inline assembly"),
+            ReallocateNonBasePtr =>
+                write!(f, "tried to reallocate with a pointer not to the beginning of an \
+                    existing object"),
+            DeallocateNonBasePtr =>
+                write!(f, "tried to deallocate with a pointer not to the beginning of an \
+                    existing object"),
+            HeapAllocZeroBytes =>
+                write!(f, "tried to re-, de- or allocate zero bytes on the heap"),
+            Unreachable =>
+                write!(f, "entered unreachable code"),
+            ReadFromReturnPointer =>
+                write!(f, "tried to read from the return pointer"),
+            UnimplementedTraitSelection =>
+                write!(f, "there were unresolved type arguments during trait selection"),
+            TypeckError =>
+                write!(f, "encountered constants with type errors, stopping evaluation"),
+            TooGeneric =>
+                write!(f, "encountered overly generic constant"),
+            ReferencedConstant =>
+                write!(f, "referenced constant has errors"),
+            InfiniteLoop =>
+                write!(f, "duplicate interpreter state observed here, const evaluation will never \
+                    terminate"),
+            InvalidBoolOp(_) =>
+                write!(f, "invalid boolean operation"),
+            UnterminatedCString(_) =>
+                write!(f, "attempted to get length of a null terminated string, but no null \
+                    found before end of allocation"),
+            ReadUndefBytes(_) =>
+                write!(f, "attempted to read undefined bytes"),
+            HeapAllocNonPowerOfTwoAlignment(_) =>
+                write!(f, "tried to re-, de-, or allocate heap memory with alignment that is \
+                    not a power of two"),
+            MachineError(ref msg) |
+            Unimplemented(ref msg) |
+            AbiViolation(ref msg) |
+            Intrinsic(ref msg) =>
+                write!(f, "{}", msg),
+            Panic(ref msg) =>
+                write!(f, "{:?}", msg),
         }
     }
 }
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index b1b6be4ae17..b3d92e8a604 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -7,7 +7,7 @@
 use crate::hir::def::{CtorKind, Namespace};
 use crate::hir::def_id::DefId;
 use crate::hir::{self, InlineAsm as HirInlineAsm};
-use crate::mir::interpret::{ConstValue, PanicMessage, InterpError::Panic, Scalar};
+use crate::mir::interpret::{ConstValue, PanicMessage, Scalar};
 use crate::mir::visit::MirVisitable;
 use crate::rustc_serialize as serialize;
 use crate::ty::adjustment::PointerCast;
@@ -3152,13 +3152,16 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
                 }
             }
             Assert { ref cond, expected, ref msg, target, cleanup } => {
-                let msg = if let Panic(PanicMessage::BoundsCheck { ref len, ref index }) = *msg {
-                    Panic(PanicMessage::BoundsCheck {
-                        len: len.fold_with(folder),
-                        index: index.fold_with(folder),
-                    })
-                } else {
-                    msg.clone()
+                use PanicMessage::*;
+                let msg = match msg {
+                    BoundsCheck { ref len, ref index } =>
+                        BoundsCheck {
+                            len: len.fold_with(folder),
+                            index: index.fold_with(folder),
+                        },
+                    Panic { .. } | Overflow(_) | OverflowNeg | DivisionByZero | RemainderByZero |
+                    GeneratorResumedAfterReturn | GeneratorResumedAfterPanic =>
+                        msg.clone(),
                 };
                 Assert { cond: cond.fold_with(folder), expected, msg, target, cleanup }
             }
@@ -3197,10 +3200,14 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
             }
             Assert { ref cond, ref msg, .. } => {
                 if cond.visit_with(visitor) {
-                    if let Panic(PanicMessage::BoundsCheck { ref len, ref index }) = *msg {
-                        len.visit_with(visitor) || index.visit_with(visitor)
-                    } else {
-                        false
+                    use PanicMessage::*;
+                    match msg {
+                        BoundsCheck { ref len, ref index } =>
+                            len.visit_with(visitor) || index.visit_with(visitor),
+                        Panic { .. } | Overflow(_) | OverflowNeg |
+                        DivisionByZero | RemainderByZero |
+                        GeneratorResumedAfterReturn | GeneratorResumedAfterPanic =>
+                            false
                     }
                 } else {
                     false
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index dca56cc526c..7562981f94f 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -514,11 +514,16 @@ macro_rules! make_mir_visitor {
             fn super_assert_message(&mut self,
                                     msg: & $($mutability)? AssertMessage<'tcx>,
                                     location: Location) {
-                use crate::mir::interpret::InterpError::*;
-                use crate::mir::interpret::PanicMessage::BoundsCheck;
-                if let Panic(BoundsCheck { len, index }) = msg {
-                    self.visit_operand(len, location);
-                    self.visit_operand(index, location);
+                use crate::mir::interpret::PanicMessage::*;
+                match msg {
+                    BoundsCheck { len, index } => {
+                        self.visit_operand(len, location);
+                        self.visit_operand(index, location);
+                    }
+                    Panic { .. } | Overflow(_) | OverflowNeg | DivisionByZero | RemainderByZero |
+                    GeneratorResumedAfterReturn | GeneratorResumedAfterPanic => {
+                        // Nothing to visit
+                    }
                 }
             }
 
diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs
index c0a446157d3..18611c3e167 100644
--- a/src/librustc_codegen_ssa/mir/block.rs
+++ b/src/librustc_codegen_ssa/mir/block.rs
@@ -2,7 +2,7 @@ use rustc::middle::lang_items;
 use rustc::ty::{self, Ty, TypeFoldable, Instance};
 use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, FnTypeExt};
 use rustc::mir::{self, Place, PlaceBase, Static, StaticKind};
-use rustc::mir::interpret::{InterpError, PanicMessage};
+use rustc::mir::interpret::PanicMessage;
 use rustc_target::abi::call::{ArgType, FnType, PassMode, IgnoreMode};
 use rustc_target::spec::abi::Abi;
 use crate::base;
@@ -368,7 +368,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 InterpError::Panic(PanicMessage::OverflowNeg) = *msg {
+            if let PanicMessage::OverflowNeg = *msg {
                 const_cond = Some(expected);
             }
         }
@@ -402,8 +402,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         let col = bx.const_u32(loc.col.to_usize() as u32 + 1);
 
         // Put together the arguments to the panic entry point.
-        let (lang_item, args) = match *msg {
-            InterpError::Panic(PanicMessage::BoundsCheck { ref len, ref index }) => {
+        let (lang_item, args) = match msg {
+            PanicMessage::BoundsCheck { ref len, ref index } => {
                 let len = self.codegen_operand(&mut bx, len).immediate();
                 let index = self.codegen_operand(&mut bx, index).immediate();
 
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 8d27a32a285..92285c47db4 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -733,8 +733,8 @@ impl<'cx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx
                 cleanup: _,
             } => {
                 self.consume_operand(loc, (cond, span), flow_state);
-                use rustc::mir::interpret::{InterpError::Panic, PanicMessage};
-                if let Panic(PanicMessage::BoundsCheck { ref len, ref index }) = *msg {
+                use rustc::mir::interpret::PanicMessage;
+                if let PanicMessage::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/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs
index 90df0c91c72..aa9e68bd7de 100644
--- a/src/librustc_mir/borrow_check/nll/invalidation.rs
+++ b/src/librustc_mir/borrow_check/nll/invalidation.rs
@@ -207,8 +207,8 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
                 cleanup: _,
             } => {
                 self.consume_operand(location, cond);
-                use rustc::mir::interpret::{InterpError::Panic, PanicMessage::BoundsCheck};
-                if let Panic(BoundsCheck { ref len, ref index }) = *msg {
+                use rustc::mir::interpret::PanicMessage;
+                if let PanicMessage::BoundsCheck { ref len, ref index } = *msg {
                     self.consume_operand(location, len);
                     self.consume_operand(location, index);
                 }
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index 6ce2f968ed7..59a8c8d34d2 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -28,7 +28,7 @@ use rustc::infer::canonical::QueryRegionConstraints;
 use rustc::infer::outlives::env::RegionBoundPairs;
 use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin};
 use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
-use rustc::mir::interpret::{InterpError::Panic, ConstValue, PanicMessage};
+use rustc::mir::interpret::{ConstValue, PanicMessage};
 use rustc::mir::tcx::PlaceTy;
 use rustc::mir::visit::{PlaceContext, Visitor, NonMutatingUseContext};
 use rustc::mir::*;
@@ -1606,7 +1606,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     span_mirbug!(self, term, "bad Assert ({:?}, not bool", cond_ty);
                 }
 
-                if let Panic(PanicMessage::BoundsCheck { ref len, ref index }) = *msg {
+                if let PanicMessage::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/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs
index 42d08a728e0..7a428a2ec9f 100644
--- a/src/librustc_mir/build/expr/as_place.rs
+++ b/src/librustc_mir/build/expr/as_place.rs
@@ -4,7 +4,7 @@ use crate::build::expr::category::Category;
 use crate::build::ForGuard::{OutsideGuard, RefWithinGuard};
 use crate::build::{BlockAnd, BlockAndExtension, Builder};
 use crate::hair::*;
-use rustc::mir::interpret::{InterpError::Panic, PanicMessage::BoundsCheck};
+use rustc::mir::interpret::{PanicMessage::BoundsCheck};
 use rustc::mir::*;
 use rustc::ty::{CanonicalUserTypeAnnotation, Variance};
 
@@ -105,10 +105,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     ),
                 );
 
-                let msg = Panic(BoundsCheck {
+                let msg = BoundsCheck {
                     len: Operand::Move(len),
                     index: Operand::Copy(Place::from(idx)),
-                });
+                };
                 let success = this.assert(block, Operand::Move(lt), true, msg, expr_span);
                 success.and(slice.index(idx))
             }
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs
index 8790ebc4169..92daf06e6f8 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir/build/expr/as_rvalue.rs
@@ -7,7 +7,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::{InterpError::Panic, PanicMessage};
+use rustc::mir::interpret::PanicMessage;
 use rustc::mir::*;
 use rustc::ty::{self, CanonicalUserTypeAnnotation, Ty, UpvarSubsts};
 use syntax_pos::Span;
@@ -101,7 +101,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         block,
                         Operand::Move(is_min),
                         false,
-                        Panic(PanicMessage::OverflowNeg),
+                        PanicMessage::OverflowNeg,
                         expr_span,
                     );
                 }
@@ -401,7 +401,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             let val = result_value.clone().field(val_fld, ty);
             let of = result_value.field(of_fld, bool_ty);
 
-            let err = Panic(PanicMessage::Overflow(op));
+            let err = PanicMessage::Overflow(op);
 
             block = self.assert(block, Operand::Move(of), false, err, span);
 
@@ -411,11 +411,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 // Checking division and remainder is more complex, since we 1. always check
                 // and 2. there are two possible failure cases, divide-by-zero and overflow.
 
-                let (zero_err, overflow_err) = if op == BinOp::Div {
-                    (Panic(PanicMessage::DivisionByZero), Panic(PanicMessage::Overflow(op)))
+                let zero_err = if op == BinOp::Div {
+                    PanicMessage::DivisionByZero
                 } else {
-                    (Panic(PanicMessage::RemainderByZero), Panic(PanicMessage::Overflow(op)))
+                    PanicMessage::RemainderByZero
                 };
+                let overflow_err = PanicMessage::Overflow(op);
 
                 // Check for / 0
                 let is_zero = self.temp(bool_ty, span);
diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs
index a85b77c7b81..27bd0f88896 100644
--- a/src/librustc_mir/interpret/terminator.rs
+++ b/src/librustc_mir/interpret/terminator.rs
@@ -7,7 +7,7 @@ use syntax::source_map::Span;
 use rustc_target::spec::abi::Abi;
 
 use super::{
-    InterpResult, PointerArithmetic, InterpError, Scalar, PanicMessage,
+    InterpResult, PointerArithmetic, InterpError, Scalar,
     InterpCx, Machine, Immediate, OpTy, ImmTy, PlaceTy, MPlaceTy, StackPopCleanup, FnVal,
 };
 
@@ -135,28 +135,31 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     self.goto_block(Some(target))?;
                 } else {
                     // Compute error message
-                    use rustc::mir::interpret::InterpError::*;
-                    return match *msg {
-                        Panic(PanicMessage::BoundsCheck { ref len, ref index }) => {
+                    use rustc::mir::interpret::PanicMessage::*;
+                    return match msg {
+                        BoundsCheck { ref len, ref index } => {
                             let len = self.read_immediate(self.eval_operand(len, None)?)
                                 .expect("can't eval len").to_scalar()?
                                 .to_bits(self.memory().pointer_size())? as u64;
                             let index = self.read_immediate(self.eval_operand(index, None)?)
                                 .expect("can't eval index").to_scalar()?
                                 .to_bits(self.memory().pointer_size())? as u64;
-                            err!(Panic(PanicMessage::BoundsCheck { len, index }))
+                            err!(Panic(BoundsCheck { len, index }))
                         }
-                        Panic(PanicMessage::Overflow(op)) =>
-                            Err(Panic(PanicMessage::Overflow(op)).into()),
-                        Panic(PanicMessage::OverflowNeg) =>
-                            Err(Panic(PanicMessage::OverflowNeg).into()),
-                        Panic(PanicMessage::DivisionByZero) =>
-                            Err(Panic(PanicMessage::DivisionByZero).into()),
-                        Panic(PanicMessage::RemainderByZero) =>
-                            Err(Panic(PanicMessage::RemainderByZero).into()),
-                        GeneratorResumedAfterReturn |
-                        GeneratorResumedAfterPanic => unimplemented!(),
-                        _ => bug!(),
+                        Overflow(op) =>
+                            err!(Panic(Overflow(*op))),
+                        OverflowNeg =>
+                            err!(Panic(OverflowNeg)),
+                        DivisionByZero =>
+                            err!(Panic(DivisionByZero)),
+                        RemainderByZero =>
+                            err!(Panic(RemainderByZero)),
+                        GeneratorResumedAfterReturn =>
+                            err!(Panic(GeneratorResumedAfterReturn)),
+                        GeneratorResumedAfterPanic =>
+                            err!(Panic(GeneratorResumedAfterPanic)),
+                        Panic { .. } =>
+                            bug!("`Panic` variant cannot occur in MIR"),
                     };
                 }
             }
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 37fcd744a38..7a2d78b2e98 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -13,7 +13,7 @@ use rustc::mir::{
 use rustc::mir::visit::{
     Visitor, PlaceContext, MutatingUseContext, MutVisitor, NonMutatingUseContext,
 };
-use rustc::mir::interpret::{InterpError::Panic, Scalar, GlobalId, InterpResult, PanicMessage};
+use rustc::mir::interpret::{Scalar, GlobalId, InterpResult, InterpError, PanicMessage};
 use rustc::ty::{self, Instance, ParamEnv, Ty, TyCtxt};
 use syntax_pos::{Span, DUMMY_SP};
 use rustc::ty::subst::InternalSubsts;
@@ -314,8 +314,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                     | HeapAllocNonPowerOfTwoAlignment(_)
                     | Unreachable
                     | ReadFromReturnPointer
-                    | GeneratorResumedAfterReturn
-                    | GeneratorResumedAfterPanic
                     | ReferencedConstant
                     | InfiniteLoop
                     => {
@@ -595,7 +593,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                     )
                 } else {
                     if overflow {
-                        let err = Panic(PanicMessage::Overflow(op)).into();
+                        let err = InterpError::Panic(PanicMessage::Overflow(op)).into();
                         let _: Option<()> = self.use_ecx(source_info, |_| Err(err));
                         return None;
                     }
@@ -809,7 +807,7 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
         self.super_terminator(terminator, location);
         let source_info = terminator.source_info;
         match &mut terminator.kind {
-            TerminatorKind::Assert { expected, msg, ref mut cond, .. } => {
+            TerminatorKind::Assert { expected, ref msg, ref mut cond, .. } => {
                 if let Some(value) = self.eval_operand(&cond, source_info) {
                     trace!("assertion on {:?} should be {:?}", value, expected);
                     let expected = ScalarMaybeUndef::from(Scalar::from_bool(*expected));
@@ -831,13 +829,13 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
                             .hir()
                             .as_local_hir_id(self.source.def_id())
                             .expect("some part of a failing const eval must be local");
-                        use rustc::mir::interpret::InterpError::*;
                         let msg = match msg {
-                            Panic(PanicMessage::Overflow(_)) |
-                            Panic(PanicMessage::OverflowNeg) |
-                            Panic(PanicMessage::DivisionByZero) |
-                            Panic(PanicMessage::RemainderByZero) => msg.description().to_owned(),
-                            Panic(PanicMessage::BoundsCheck { ref len, ref index }) => {
+                            PanicMessage::Overflow(_) |
+                            PanicMessage::OverflowNeg |
+                            PanicMessage::DivisionByZero |
+                            PanicMessage::RemainderByZero =>
+                                msg.description().to_owned(),
+                            PanicMessage::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 af412edbdc2..5461a2e470c 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -1016,7 +1016,7 @@ fn create_generator_resume_function<'tcx>(
 
     let mut cases = create_cases(body, &transform, |point| Some(point.resume));
 
-    use rustc::mir::interpret::InterpError::{
+    use rustc::mir::interpret::PanicMessage::{
         GeneratorResumedAfterPanic,
         GeneratorResumedAfterReturn,
     };