about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/ich/impls_mir.rs21
-rw-r--r--src/librustc/ich/impls_ty.rs13
-rw-r--r--src/librustc/mir/interpret/error.rs39
-rw-r--r--src/librustc/mir/interpret/mod.rs2
-rw-r--r--src/librustc/mir/mod.rs37
-rw-r--r--src/librustc/mir/visit.rs14
-rw-r--r--src/librustc/ty/structural_impls.rs23
-rw-r--r--src/librustc_mir/borrow_check/mod.rs22
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs3
-rw-r--r--src/librustc_mir/build/expr/as_place.rs3
-rw-r--r--src/librustc_mir/build/expr/as_rvalue.rs9
-rw-r--r--src/librustc_mir/interpret/terminator/mod.rs9
-rw-r--r--src/librustc_mir/transform/const_prop.rs12
-rw-r--r--src/librustc_mir/transform/generator.rs9
-rw-r--r--src/librustc_passes/mir_stats.rs13
-rw-r--r--src/librustc_trans/mir/block.rs29
16 files changed, 111 insertions, 147 deletions
diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs
index 437626ff536..33f43e53394 100644
--- a/src/librustc/ich/impls_mir.rs
+++ b/src/librustc/ich/impls_mir.rs
@@ -227,27 +227,6 @@ for mir::TerminatorKind<'gcx> {
     }
 }
 
-impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
-for mir::AssertMessage<'gcx> {
-    fn hash_stable<W: StableHasherResult>(&self,
-                                          hcx: &mut StableHashingContext<'a>,
-                                          hasher: &mut StableHasher<W>) {
-        mem::discriminant(self).hash_stable(hcx, hasher);
-
-        match *self {
-            mir::AssertMessage::BoundsCheck { ref len, ref index } => {
-                len.hash_stable(hcx, hasher);
-                index.hash_stable(hcx, hasher);
-            }
-            mir::AssertMessage::Math(ref const_math_err) => {
-                const_math_err.hash_stable(hcx, hasher);
-            }
-            mir::AssertMessage::GeneratorResumedAfterReturn => (),
-            mir::AssertMessage::GeneratorResumedAfterPanic => (),
-        }
-    }
-}
-
 impl_stable_hash_for!(struct mir::Statement<'tcx> { source_info, kind });
 
 impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index a5447a3145a..a40d8e09277 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -535,8 +535,8 @@ for ::mir::interpret::EvalError<'gcx> {
     }
 }
 
-impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
-for ::mir::interpret::EvalErrorKind<'gcx> {
+impl<'a, 'gcx, O: HashStable<StableHashingContext<'a>>> HashStable<StableHashingContext<'a>>
+for ::mir::interpret::EvalErrorKind<'gcx, O> {
     fn hash_stable<W: StableHasherResult>(&self,
                                           hcx: &mut StableHashingContext<'a>,
                                           hasher: &mut StableHasher<W>) {
@@ -578,6 +578,8 @@ for ::mir::interpret::EvalErrorKind<'gcx> {
             OverflowNeg |
             RemainderByZero |
             DivisionByZero |
+            GeneratorResumedAfterReturn |
+            GeneratorResumedAfterPanic |
             ReferencedConstant => {}
             MachineError(ref err) => err.hash_stable(hcx, hasher),
             FunctionPointerTyMismatch(a, b) => {
@@ -597,10 +599,9 @@ for ::mir::interpret::EvalErrorKind<'gcx> {
             },
             InvalidBoolOp(bop) => bop.hash_stable(hcx, hasher),
             Unimplemented(ref s) => s.hash_stable(hcx, hasher),
-            ArrayIndexOutOfBounds(sp, a, b) => {
-                sp.hash_stable(hcx, hasher);
-                a.hash_stable(hcx, hasher);
-                b.hash_stable(hcx, hasher)
+            BoundsCheck { ref len, ref index } => {
+                len.hash_stable(hcx, hasher);
+                index.hash_stable(hcx, hasher)
             },
             Intrinsic(ref s) => s.hash_stable(hcx, hasher),
             InvalidChar(c) => c.hash_stable(hcx, hasher),
diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs
index 022b82841bc..1e1d50c3fc0 100644
--- a/src/librustc/mir/interpret/error.rs
+++ b/src/librustc/mir/interpret/error.rs
@@ -7,17 +7,16 @@ use super::{
     MemoryPointer, Lock, AccessKind
 };
 
-use syntax::codemap::Span;
 use backtrace::Backtrace;
 
 #[derive(Debug, Clone)]
 pub struct EvalError<'tcx> {
-    pub kind: EvalErrorKind<'tcx>,
+    pub kind: EvalErrorKind<'tcx, u64>,
     pub backtrace: Option<Backtrace>,
 }
 
-impl<'tcx> From<EvalErrorKind<'tcx>> for EvalError<'tcx> {
-    fn from(kind: EvalErrorKind<'tcx>) -> Self {
+impl<'tcx> From<EvalErrorKind<'tcx, u64>> for EvalError<'tcx> {
+    fn from(kind: EvalErrorKind<'tcx, u64>) -> Self {
         let backtrace = match env::var("MIRI_BACKTRACE") {
             Ok(ref val) if !val.is_empty() => Some(Backtrace::new_unresolved()),
             _ => None
@@ -29,8 +28,10 @@ impl<'tcx> From<EvalErrorKind<'tcx>> for EvalError<'tcx> {
     }
 }
 
-#[derive(Debug, Clone, RustcEncodable, RustcDecodable)]
-pub enum EvalErrorKind<'tcx> {
+pub type AssertMessage<'tcx> = EvalErrorKind<'tcx, mir::Operand<'tcx>>;
+
+#[derive(Clone, RustcEncodable, RustcDecodable)]
+pub enum EvalErrorKind<'tcx, O> {
     /// This variant is used by machines to signal their own errors that do not
     /// match an existing variant
     MachineError(String),
@@ -58,7 +59,7 @@ pub enum EvalErrorKind<'tcx> {
     Unimplemented(String),
     DerefFunctionPointer,
     ExecuteMemory,
-    ArrayIndexOutOfBounds(Span, u64, u64),
+    BoundsCheck { len: O, index: O },
     Overflow(mir::BinOp),
     OverflowNeg,
     DivisionByZero,
@@ -121,11 +122,13 @@ pub enum EvalErrorKind<'tcx> {
     /// Cannot compute this constant because it depends on another one
     /// which already produced an error
     ReferencedConstant,
+    GeneratorResumedAfterReturn,
+    GeneratorResumedAfterPanic,
 }
 
 pub type EvalResult<'tcx, T = ()> = Result<T, EvalError<'tcx>>;
 
-impl<'tcx> EvalErrorKind<'tcx> {
+impl<'tcx, O> EvalErrorKind<'tcx, O> {
     pub fn description(&self) -> &str {
         use self::EvalErrorKind::*;
         match *self {
@@ -175,7 +178,7 @@ impl<'tcx> EvalErrorKind<'tcx> {
                 "tried to dereference a function pointer",
             ExecuteMemory =>
                 "tried to treat a memory pointer as a function pointer",
-            ArrayIndexOutOfBounds(..) =>
+            BoundsCheck{..} =>
                 "array index out of bounds",
             Intrinsic(..) =>
                 "intrinsic failed",
@@ -228,7 +231,7 @@ impl<'tcx> EvalErrorKind<'tcx> {
                 "the evaluated program panicked",
             ReadFromReturnPointer =>
                 "tried to read from the return pointer",
-            EvalErrorKind::PathNotFound(_) =>
+            PathNotFound(_) =>
                 "a path could not be resolved, maybe the crate is not loaded",
             UnimplementedTraitSelection =>
                 "there were unresolved type arguments during trait selection",
@@ -247,14 +250,22 @@ impl<'tcx> EvalErrorKind<'tcx> {
             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",
         }
     }
 }
 
 impl<'tcx> fmt::Display for EvalError<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{:?}", self.kind)
+    }
+}
+
+impl<'tcx, O: fmt::Debug> fmt::Debug for EvalErrorKind<'tcx, O> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         use self::EvalErrorKind::*;
-        match self.kind {
+        match *self {
             PointerOutOfBounds { ptr, access, allocation_size } => {
                 write!(f, "{} at offset {}, outside bounds of allocation {} which has size {}",
                        if access { "memory access" } else { "pointer computed" },
@@ -282,8 +293,8 @@ impl<'tcx> fmt::Display for EvalError<'tcx> {
             NoMirFor(ref func) => write!(f, "no mir for `{}`", func),
             FunctionPointerTyMismatch(sig, got) =>
                 write!(f, "tried to call a function with sig {} through a function pointer of type {}", sig, got),
-            ArrayIndexOutOfBounds(span, len, index) =>
-                write!(f, "index out of bounds: the len is {} but the index is {} at {:?}", len, index, span),
+            BoundsCheck { ref len, ref index } =>
+                write!(f, "index out of bounds: the len is {:?} but the index is {:?}", len, index),
             ReallocatedWrongMemoryKind(ref old, ref new) =>
                 write!(f, "tried to reallocate memory from {} to {}", old, new),
             DeallocatedWrongMemoryKind(ref old, ref new) =>
@@ -305,7 +316,7 @@ impl<'tcx> fmt::Display for EvalError<'tcx> {
                 write!(f, "{}", inner),
             IncorrectAllocationInformation(size, size2, align, align2) =>
                 write!(f, "incorrect alloc info: expected size {} and align {}, got size {} and align {}", size, align, size2, align2),
-            _ => write!(f, "{}", self.kind.description()),
+            _ => write!(f, "{}", self.description()),
         }
     }
 }
diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs
index a521caf4fda..546c7a920d5 100644
--- a/src/librustc/mir/interpret/mod.rs
+++ b/src/librustc/mir/interpret/mod.rs
@@ -8,7 +8,7 @@ macro_rules! err {
 mod error;
 mod value;
 
-pub use self::error::{EvalError, EvalResult, EvalErrorKind};
+pub use self::error::{EvalError, EvalResult, EvalErrorKind, AssertMessage};
 
 pub use self::value::{PrimVal, PrimValKind, Value, Pointer};
 
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index 0b56dbda42c..c62fe0372df 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -45,6 +45,8 @@ use syntax_pos::{Span, DUMMY_SP};
 use rustc_apfloat::ieee::{Single, Double};
 use rustc_apfloat::Float;
 
+pub use mir::interpret::AssertMessage;
+
 mod cache;
 pub mod tcx;
 pub mod visit;
@@ -1132,23 +1134,7 @@ impl<'tcx> TerminatorKind<'tcx> {
                     write!(fmt, "!")?;
                 }
                 write!(fmt, "{:?}, ", cond)?;
-
-                match *msg {
-                    AssertMessage::BoundsCheck { ref len, ref index } => {
-                        write!(fmt, "{:?}, {:?}, {:?}",
-                               "index out of bounds: the len is {} but the index is {}",
-                               len, index)?;
-                    }
-                    AssertMessage::Math(ref err) => {
-                        write!(fmt, "{:?}", err.description())?;
-                    }
-                    AssertMessage::GeneratorResumedAfterReturn => {
-                        write!(fmt, "{:?}", "generator resumed after completion")?;
-                    }
-                    AssertMessage::GeneratorResumedAfterPanic => {
-                        write!(fmt, "{:?}", "generator resumed after panicking")?;
-                    }
-                }
+                write!(fmt, "{:?}", msg)?;
 
                 write!(fmt, ")")
             },
@@ -1205,17 +1191,6 @@ impl<'tcx> TerminatorKind<'tcx> {
     }
 }
 
-#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
-pub enum AssertMessage<'tcx> {
-    BoundsCheck {
-        len: Operand<'tcx>,
-        index: Operand<'tcx>
-    },
-    Math(EvalErrorKind<'tcx>),
-    GeneratorResumedAfterReturn,
-    GeneratorResumedAfterPanic,
-}
-
 ///////////////////////////////////////////////////////////////////////////
 // Statements
 
@@ -2281,8 +2256,8 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
                 }
             },
             Assert { ref cond, expected, ref msg, target, cleanup } => {
-                let msg = if let AssertMessage::BoundsCheck { ref len, ref index } = *msg {
-                    AssertMessage::BoundsCheck {
+                let msg = if let EvalErrorKind::BoundsCheck { ref len, ref index } = *msg {
+                    EvalErrorKind::BoundsCheck {
                         len: len.fold_with(folder),
                         index: index.fold_with(folder),
                     }
@@ -2331,7 +2306,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
             },
             Assert { ref cond, ref msg, .. } => {
                 if cond.visit_with(visitor) {
-                    if let AssertMessage::BoundsCheck { ref len, ref index } = *msg {
+                    if let EvalErrorKind::BoundsCheck { ref len, ref index } = *msg {
                         len.visit_with(visitor) || index.visit_with(visitor)
                     } else {
                         false
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index a3fdb6f73ab..59b6f369754 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -511,17 +511,13 @@ macro_rules! make_mir_visitor {
             fn super_assert_message(&mut self,
                                     msg: & $($mutability)* AssertMessage<'tcx>,
                                     location: Location) {
-                match *msg {
-                    AssertMessage::BoundsCheck {
+                use mir::interpret::EvalErrorKind::*;
+                if let BoundsCheck {
                         ref $($mutability)* len,
                         ref $($mutability)* index
-                    } => {
-                        self.visit_operand(len, location);
-                        self.visit_operand(index, location);
-                    }
-                    AssertMessage::Math(_) => {},
-                    AssertMessage::GeneratorResumedAfterReturn => {},
-                    AssertMessage::GeneratorResumedAfterPanic => {},
+                    } = *msg {
+                    self.visit_operand(len, location);
+                    self.visit_operand(index, location);
                 }
             }
 
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index bae91d064a5..d4ed6c60e0e 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -474,8 +474,18 @@ impl<'a, 'tcx> Lift<'tcx> for ConstEvalErr<'a> {
 impl<'a, 'tcx> Lift<'tcx> for interpret::EvalError<'a> {
     type Lifted = interpret::EvalError<'tcx>;
     fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
+        Some(interpret::EvalError {
+            kind: tcx.lift(&self.kind)?,
+            backtrace: self.backtrace.clone(),
+        })
+    }
+}
+
+impl<'a, 'tcx, O: Lift<'tcx>> Lift<'tcx> for interpret::EvalErrorKind<'a, O> {
+    type Lifted = interpret::EvalErrorKind<'tcx, <O as Lift<'tcx>>::Lifted>;
+    fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
         use ::mir::interpret::EvalErrorKind::*;
-        let kind = match self.kind {
+        Some(match *self {
             MachineError(ref err) => MachineError(err.clone()),
             FunctionPointerTyMismatch(a, b) => FunctionPointerTyMismatch(
                 tcx.lift(&a)?,
@@ -504,7 +514,10 @@ impl<'a, 'tcx> Lift<'tcx> for interpret::EvalError<'a> {
             Unimplemented(ref s) => Unimplemented(s.clone()),
             DerefFunctionPointer => DerefFunctionPointer,
             ExecuteMemory => ExecuteMemory,
-            ArrayIndexOutOfBounds(sp, a, b) => ArrayIndexOutOfBounds(sp, a, b),
+            BoundsCheck { ref len, ref index } => BoundsCheck {
+                len: tcx.lift(len)?,
+                index: tcx.lift(index)?,
+            },
             Intrinsic(ref s) => Intrinsic(s.clone()),
             InvalidChar(c) => InvalidChar(c),
             StackFrameLimitReached => StackFrameLimitReached,
@@ -570,10 +583,8 @@ impl<'a, 'tcx> Lift<'tcx> for interpret::EvalError<'a> {
             Overflow(op) => Overflow(op),
             DivisionByZero => DivisionByZero,
             RemainderByZero => RemainderByZero,
-        };
-        Some(interpret::EvalError {
-            kind: kind,
-            backtrace: self.backtrace.clone(),
+            GeneratorResumedAfterReturn => GeneratorResumedAfterReturn,
+            GeneratorResumedAfterPanic => GeneratorResumedAfterPanic,
         })
     }
 }
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 3145be7df85..7e1c20dff6a 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -18,7 +18,7 @@ use rustc::infer::InferCtxt;
 use rustc::ty::{self, ParamEnv, TyCtxt};
 use rustc::ty::maps::Providers;
 use rustc::lint::builtin::UNUSED_MUT;
-use rustc::mir::{AssertMessage, AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
+use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
 use rustc::mir::{ClearCrossCrate, Local, Location, Place, Mir, Mutability, Operand};
 use rustc::mir::{Projection, ProjectionElem, Rvalue, Field, Statement, StatementKind};
 use rustc::mir::{Terminator, TerminatorKind};
@@ -586,18 +586,14 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
                 cleanup: _,
             } => {
                 self.consume_operand(ContextKind::Assert.new(loc), (cond, span), flow_state);
-                match *msg {
-                    AssertMessage::BoundsCheck { ref len, ref index } => {
-                        self.consume_operand(ContextKind::Assert.new(loc), (len, span), flow_state);
-                        self.consume_operand(
-                            ContextKind::Assert.new(loc),
-                            (index, span),
-                            flow_state,
-                        );
-                    }
-                    AssertMessage::Math(_ /*const_math_err*/) => {}
-                    AssertMessage::GeneratorResumedAfterReturn => {}
-                    AssertMessage::GeneratorResumedAfterPanic => {}
+                use rustc::mir::interpret::EvalErrorKind::BoundsCheck;
+                if let BoundsCheck { ref len, ref index } = *msg {
+                    self.consume_operand(ContextKind::Assert.new(loc), (len, span), flow_state);
+                    self.consume_operand(
+                        ContextKind::Assert.new(loc),
+                        (index, span),
+                        flow_state,
+                    );
                 }
             }
 
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 a811b2c147e..a21b9196bad 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -22,6 +22,7 @@ use rustc::infer::region_constraints::{GenericKind, RegionConstraintData};
 use rustc::infer::{InferCtxt, InferOk, InferResult, LateBoundRegionConversionTime, UnitResult};
 use rustc::mir::tcx::PlaceTy;
 use rustc::mir::visit::{PlaceContext, Visitor};
+use rustc::mir::interpret::EvalErrorKind::BoundsCheck;
 use rustc::mir::*;
 use rustc::traits::query::NoSolution;
 use rustc::traits::{self, Normalized, TraitEngine};
@@ -928,7 +929,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                     span_mirbug!(self, term, "bad Assert ({:?}, not bool", cond_ty);
                 }
 
-                if let AssertMessage::BoundsCheck { ref len, ref index } = *msg {
+                if let BoundsCheck { ref len, ref index } = *msg {
                     if len.ty(mir, 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 9e217908511..19ec13324d6 100644
--- a/src/librustc_mir/build/expr/as_place.rs
+++ b/src/librustc_mir/build/expr/as_place.rs
@@ -14,6 +14,7 @@ use build::{BlockAnd, BlockAndExtension, Builder};
 use build::expr::category::Category;
 use hair::*;
 use rustc::mir::*;
+use rustc::mir::interpret::EvalErrorKind::BoundsCheck;
 
 use rustc_data_structures::indexed_vec::Idx;
 
@@ -73,7 +74,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                                                            Operand::Copy(Place::Local(idx)),
                                                            Operand::Copy(len.clone())));
 
-                let msg = AssertMessage::BoundsCheck {
+                let msg = BoundsCheck {
                     len: Operand::Move(len),
                     index: Operand::Copy(Place::Local(idx))
                 };
diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs
index 33c80ab22a3..9e96fdf8214 100644
--- a/src/librustc_mir/build/expr/as_rvalue.rs
+++ b/src/librustc_mir/build/expr/as_rvalue.rs
@@ -85,9 +85,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     this.cfg.push_assign(block, source_info, &is_min,
                                          Rvalue::BinaryOp(BinOp::Eq, arg.to_copy(), minval));
 
-                    let err = EvalErrorKind::OverflowNeg;
                     block = this.assert(block, Operand::Move(is_min), false,
-                                        AssertMessage::Math(err), expr_span);
+                                        EvalErrorKind::OverflowNeg, expr_span);
                 }
                 block.and(Rvalue::UnaryOp(op, arg))
             }
@@ -313,7 +312,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             let err = EvalErrorKind::Overflow(op);
 
             block = self.assert(block, Operand::Move(of), false,
-                                AssertMessage::Math(err), span);
+                                err, span);
 
             block.and(Rvalue::Use(Operand::Move(val)))
         } else {
@@ -336,7 +335,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                                      Rvalue::BinaryOp(BinOp::Eq, rhs.to_copy(), zero));
 
                 block = self.assert(block, Operand::Move(is_zero), false,
-                                    AssertMessage::Math(zero_err), span);
+                                    zero_err, span);
 
                 // We only need to check for the overflow in one case:
                 // MIN / -1, and only for signed values.
@@ -361,7 +360,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                                          Rvalue::BinaryOp(BinOp::BitAnd, is_neg_1, is_min));
 
                     block = self.assert(block, Operand::Move(of), false,
-                                        AssertMessage::Math(overflow_err), span);
+                                        overflow_err, span);
                 }
             }
 
diff --git a/src/librustc_mir/interpret/terminator/mod.rs b/src/librustc_mir/interpret/terminator/mod.rs
index 4f0e97f6e1a..b630725b0d2 100644
--- a/src/librustc_mir/interpret/terminator/mod.rs
+++ b/src/librustc_mir/interpret/terminator/mod.rs
@@ -148,21 +148,22 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
                 if expected == cond_val {
                     self.goto_block(target);
                 } else {
-                    use rustc::mir::AssertMessage::*;
+                    use rustc::mir::interpret::EvalErrorKind::*;
                     return match *msg {
                         BoundsCheck { ref len, ref index } => {
-                            let span = terminator.source_info.span;
                             let len = self.eval_operand_to_primval(len)
                                 .expect("can't eval len")
                                 .to_u64()?;
                             let index = self.eval_operand_to_primval(index)
                                 .expect("can't eval index")
                                 .to_u64()?;
-                            err!(ArrayIndexOutOfBounds(span, len, index))
+                            err!(BoundsCheck { len, index })
                         }
-                        Math(ref err) => Err(err.clone().into()),
+                        Overflow(op) => Err(Overflow(op).into()),
+                        OverflowNeg => Err(OverflowNeg.into()),
                         GeneratorResumedAfterReturn |
                         GeneratorResumedAfterPanic => unimplemented!(),
+                        _ => bug!(),
                     };
                 }
             }
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 192ab6e17e7..e1db216b6bb 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -478,12 +478,12 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
                         .hir
                         .as_local_node_id(self.source.def_id)
                         .expect("some part of a failing const eval must be local");
-                    use rustc::mir::AssertMessage::*;
+                    use rustc::mir::interpret::EvalErrorKind::*;
                     let msg = match msg {
-                        // Need proper const propagator for these
-                        GeneratorResumedAfterReturn |
-                        GeneratorResumedAfterPanic => return,
-                        Math(ref err) => err.description().to_owned(),
+                        Overflow(_) |
+                        OverflowNeg |
+                        DivisionByZero |
+                        RemainderByZero => msg.description().to_owned(),
                         BoundsCheck { ref len, ref index } => {
                             let len = self.eval_operand(len).expect("len must be const");
                             let len = match len.0 {
@@ -504,6 +504,8 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
                                 index,
                             )
                         },
+                        // Need proper const propagator for these
+                        _ => return,
                     };
                     self.tcx.lint_node(
                         ::rustc::lint::builtin::CONST_ERR,
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index 0ff73569433..36735586e81 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -738,12 +738,17 @@ fn create_generator_resume_function<'a, 'tcx>(
 
     let mut cases = create_cases(mir, &transform, |point| Some(point.resume));
 
+    use rustc::mir::interpret::EvalErrorKind::{
+        GeneratorResumedAfterPanic,
+        GeneratorResumedAfterReturn,
+    };
+
     // Jump to the entry point on the 0 state
     cases.insert(0, (0, BasicBlock::new(0)));
     // Panic when resumed on the returned (1) state
-    cases.insert(1, (1, insert_panic_block(tcx, mir, AssertMessage::GeneratorResumedAfterReturn)));
+    cases.insert(1, (1, insert_panic_block(tcx, mir, GeneratorResumedAfterReturn)));
     // Panic when resumed on the poisoned (2) state
-    cases.insert(2, (2, insert_panic_block(tcx, mir, AssertMessage::GeneratorResumedAfterPanic)));
+    cases.insert(2, (2, insert_panic_block(tcx, mir, GeneratorResumedAfterPanic)));
 
     insert_switch(tcx, mir, cases, &transform, TerminatorKind::Unreachable);
 
diff --git a/src/librustc_passes/mir_stats.rs b/src/librustc_passes/mir_stats.rs
index a4e056c6b58..45c6e89321d 100644
--- a/src/librustc_passes/mir_stats.rs
+++ b/src/librustc_passes/mir_stats.rs
@@ -18,6 +18,7 @@ use rustc::mir::{Place, PlaceElem, PlaceProjection};
 use rustc::mir::{Mir, Operand, ProjectionElem};
 use rustc::mir::{Rvalue, SourceInfo, Statement, StatementKind};
 use rustc::mir::{Terminator, TerminatorKind, VisibilityScope, VisibilityScopeData};
+use rustc::mir::interpret::EvalErrorKind;
 use rustc::mir::visit as mir_visit;
 use rustc::ty::{self, ClosureSubsts, TyCtxt};
 use rustc::util::nodemap::{FxHashMap};
@@ -133,14 +134,18 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> {
                             location: Location) {
         self.record("AssertMessage", msg);
         self.record(match *msg {
-            AssertMessage::BoundsCheck { .. } => "AssertMessage::BoundsCheck",
-            AssertMessage::Math(..) => "AssertMessage::Math",
-            AssertMessage::GeneratorResumedAfterReturn => {
+            EvalErrorKind::BoundsCheck { .. } => "AssertMessage::BoundsCheck",
+            EvalErrorKind::Overflow(..) => "AssertMessage::Overflow",
+            EvalErrorKind::OverflowNeg => "AssertMessage::OverflowNeg",
+            EvalErrorKind::DivisionByZero => "AssertMessage::DivisionByZero",
+            EvalErrorKind::RemainderByZero => "AssertMessage::RemainderByZero",
+            EvalErrorKind::GeneratorResumedAfterReturn => {
                 "AssertMessage::GeneratorResumedAfterReturn"
             }
-            AssertMessage::GeneratorResumedAfterPanic => {
+            EvalErrorKind::GeneratorResumedAfterPanic => {
                 "AssertMessage::GeneratorResumedAfterPanic"
             }
+            _ => bug!(),
         }, msg);
         self.super_assert_message(msg, location);
     }
diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs
index 32cb6c72d58..b666c2b2115 100644
--- a/src/librustc_trans/mir/block.rs
+++ b/src/librustc_trans/mir/block.rs
@@ -13,6 +13,7 @@ use rustc::middle::lang_items;
 use rustc::ty::{self, Ty, TypeFoldable};
 use rustc::ty::layout::{self, LayoutOf};
 use rustc::mir;
+use rustc::mir::interpret::EvalErrorKind;
 use abi::{Abi, ArgType, ArgTypeExt, FnType, FnTypeExt, LlvmType, PassMode};
 use base;
 use callee;
@@ -311,9 +312,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
                 // checked operation, just a comparison with the minimum
                 // value, so we have to check for the assert message.
                 if !bx.cx.check_overflow {
-                    use rustc::mir::interpret::EvalErrorKind::OverflowNeg;
-
-                    if let mir::AssertMessage::Math(OverflowNeg) = *msg {
+                    if let mir::interpret::EvalErrorKind::OverflowNeg = *msg {
                         const_cond = Some(expected);
                     }
                 }
@@ -353,7 +352,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
 
                 // Put together the arguments to the panic entry point.
                 let (lang_item, args) = match *msg {
-                    mir::AssertMessage::BoundsCheck { ref len, ref index } => {
+                    EvalErrorKind::BoundsCheck { ref len, ref index } => {
                         let len = self.trans_operand(&mut bx, len).immediate();
                         let index = self.trans_operand(&mut bx, index).immediate();
 
@@ -365,26 +364,8 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
                         (lang_items::PanicBoundsCheckFnLangItem,
                          vec![file_line_col, index, len])
                     }
-                    mir::AssertMessage::Math(ref err) => {
-                        let msg_str = Symbol::intern(err.description()).as_str();
-                        let msg_str = C_str_slice(bx.cx, msg_str);
-                        let msg_file_line_col = C_struct(bx.cx,
-                                                     &[msg_str, filename, line, col],
-                                                     false);
-                        let msg_file_line_col = consts::addr_of(bx.cx,
-                                                                msg_file_line_col,
-                                                                align,
-                                                                "panic_loc");
-                        (lang_items::PanicFnLangItem,
-                         vec![msg_file_line_col])
-                    }
-                    mir::AssertMessage::GeneratorResumedAfterReturn |
-                    mir::AssertMessage::GeneratorResumedAfterPanic => {
-                        let str = if let mir::AssertMessage::GeneratorResumedAfterReturn = *msg {
-                            "generator resumed after completion"
-                        } else {
-                            "generator resumed after panicking"
-                        };
+                    _ => {
+                        let str = msg.description();
                         let msg_str = Symbol::intern(str).as_str();
                         let msg_str = C_str_slice(bx.cx, msg_str);
                         let msg_file_line_col = C_struct(bx.cx,