about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>2018-03-06 12:43:02 +0100
committerOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>2018-03-08 08:35:39 +0100
commitb5ace9a906d0a445420a0ff16f77ce967722ddc6 (patch)
treede379168cd41e525503f37c9196be4433057c9e2
parentedc5f7343338ddbbc2bae94be585cd821dbe8118 (diff)
downloadrust-b5ace9a906d0a445420a0ff16f77ce967722ddc6.tar.gz
rust-b5ace9a906d0a445420a0ff16f77ce967722ddc6.zip
Unify the const folding errors
before they differed depending on whether optimizations were on or not
-rw-r--r--src/librustc_mir/transform/const_prop.rs142
-rw-r--r--src/test/compile-fail/const-err-early.rs7
-rw-r--r--src/test/compile-fail/const-err-multi.rs4
-rw-r--r--src/test/compile-fail/const-err2.rs5
-rw-r--r--src/test/compile-fail/const-eval-overflow2.rs8
-rw-r--r--src/test/compile-fail/const-eval-overflow2b.rs8
-rw-r--r--src/test/compile-fail/const-eval-overflow2c.rs8
-rw-r--r--src/test/compile-fail/eval-enum.rs2
-rw-r--r--src/test/compile-fail/issue-44578.rs2
-rw-r--r--src/test/compile-fail/issue-8460-const.rs81
-rw-r--r--src/test/compile-fail/lint-exceeding-bitshifts.rs40
-rw-r--r--src/test/compile-fail/lint-exceeding-bitshifts2.rs6
-rw-r--r--src/test/ui/const-eval-overflow-4.rs1
-rw-r--r--src/test/ui/const-eval-overflow-4.stderr8
-rw-r--r--src/test/ui/const-eval/conditional_array_execution.rs3
-rw-r--r--src/test/ui/const-eval/conditional_array_execution.stderr18
-rw-r--r--src/test/ui/const-eval/issue-43197.rs6
-rw-r--r--src/test/ui/const-eval/issue-43197.stderr30
-rw-r--r--src/test/ui/const-eval/pub_const_err.rs16
-rw-r--r--src/test/ui/const-eval/pub_const_err.stderr14
-rw-r--r--src/test/ui/const-len-underflow-separate-spans.rs1
-rw-r--r--src/test/ui/const-len-underflow-separate-spans.stderr10
-rw-r--r--src/test/ui/error-codes/E0080.rs1
-rw-r--r--src/test/ui/error-codes/E0080.stderr12
24 files changed, 278 insertions, 155 deletions
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 565e5de85c1..c8e1a93cdda 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -12,10 +12,10 @@
 //! assertion failures
 
 
-
+use rustc::hir::def::Def;
 use rustc::mir::{Constant, Literal, Location, Place, Mir, Operand, Rvalue, Local};
 use rustc::mir::{NullOp, StatementKind, Statement, BasicBlock, LocalKind};
-use rustc::mir::{TerminatorKind, ClearCrossCrate, SourceInfo, BinOp};
+use rustc::mir::{TerminatorKind, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem};
 use rustc::mir::visit::{Visitor, PlaceContext};
 use rustc::middle::const_val::ConstVal;
 use rustc::ty::{TyCtxt, self, Instance};
@@ -26,6 +26,10 @@ use syntax::codemap::Span;
 use rustc::ty::subst::Substs;
 use rustc_data_structures::indexed_vec::IndexVec;
 use rustc::ty::ParamEnv;
+use rustc::ty::layout::{
+    LayoutOf, TyLayout, LayoutError,
+    HasTyCtxt, TargetDataLayout, HasDataLayout,
+};
 
 pub struct ConstProp;
 
@@ -34,6 +38,15 @@ impl MirPass for ConstProp {
                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           source: MirSource,
                           mir: &mut Mir<'tcx>) {
+        // will be evaluated by miri and produce its errors there
+        if source.promoted.is_some() {
+            return;
+        }
+        match tcx.describe_def(source.def_id) {
+            // skip statics because they'll be evaluated by miri anyway
+            Some(Def::Static(..)) => return,
+            _ => {},
+        }
         trace!("ConstProp starting for {:?}", source.def_id);
 
         // FIXME(oli-obk, eddyb) Optimize locals (or even local paths) to hold
@@ -59,6 +72,28 @@ struct ConstPropagator<'b, 'a, 'tcx:'a+'b> {
     param_env: ParamEnv<'tcx>,
 }
 
+impl<'a, 'b, 'tcx> LayoutOf<ty::Ty<'tcx>> for &'a ConstPropagator<'a, 'b, 'tcx> {
+    type TyLayout = Result<TyLayout<'tcx>, LayoutError<'tcx>>;
+
+    fn layout_of(self, ty: ty::Ty<'tcx>) -> Self::TyLayout {
+        self.tcx.layout_of(self.param_env.and(ty))
+    }
+}
+
+impl<'a, 'b, 'tcx> HasDataLayout for &'a ConstPropagator<'a, 'b, 'tcx> {
+    #[inline]
+    fn data_layout(&self) -> &TargetDataLayout {
+        &self.tcx.data_layout
+    }
+}
+
+impl<'a, 'b, 'tcx> HasTyCtxt<'tcx> for &'a ConstPropagator<'a, 'b, 'tcx> {
+    #[inline]
+    fn tcx<'c>(&'c self) -> TyCtxt<'c, 'tcx, 'tcx> {
+        self.tcx
+    }
+}
+
 impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
     fn new(
         mir: &'b Mir<'tcx>,
@@ -134,15 +169,43 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
         }
     }
 
+    fn eval_place(&mut self, place: &Place<'tcx>) -> Option<Const<'tcx>> {
+        match *place {
+            Place::Local(loc) => self.places[loc].clone(),
+            Place::Projection(ref proj) => match proj.elem {
+                ProjectionElem::Field(field, _) => {
+                    trace!("field proj on {:?}", proj.base);
+                    let (base, ty, span) = self.eval_place(&proj.base)?;
+                    match base {
+                        Value::ByValPair(a, b) => {
+                            trace!("by val pair: {:?}, {:?}", a, b);
+                            let base_layout = self.tcx.layout_of(self.param_env.and(ty)).ok()?;
+                            trace!("layout computed");
+                            use rustc_data_structures::indexed_vec::Idx;
+                            let field_index = field.index();
+                            let val = if field_index == 0 {
+                                a
+                            } else {
+                                assert_eq!(field_index, 1);
+                                b
+                            };
+                            let field = base_layout.field(&*self, field_index).ok()?;
+                            trace!("projection resulted in: {:?}", val);
+                            Some((Value::ByVal(val), field.ty, span))
+                        },
+                        _ => None,
+                    }
+                },
+                _ => None,
+            },
+            _ => None,
+        }
+    }
+
     fn eval_operand(&mut self, op: &Operand<'tcx>) -> Option<Const<'tcx>> {
         match *op {
             Operand::Constant(ref c) => self.eval_constant(c),
-            Operand::Move(ref place) | Operand::Copy(ref place) => match *place {
-                Place::Local(loc) => self.places[loc].clone(),
-                // FIXME(oli-obk): field and index projections
-                Place::Projection(_) => None,
-                _ => None,
-            },
+            Operand::Move(ref place) | Operand::Copy(ref place) => self.eval_place(place),
         }
     }
 
@@ -235,18 +298,24 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
                 let r = ecx.value_to_primval(ValTy { value: right.0, ty: right.1 }).ok()?;
                 if op == BinOp::Shr || op == BinOp::Shl {
                     let param_env = self.tcx.param_env(self.source.def_id);
-                    let bits = self.tcx.layout_of(param_env.and(place_ty)).unwrap().size.bits();
+                    let left_ty = left.ty(self.mir, self.tcx);
+                    let bits = self.tcx.layout_of(param_env.and(left_ty)).unwrap().size.bits();
                     if r.to_bytes().ok().map_or(false, |b| b >= bits as u128) {
                         let scope_info = match self.mir.visibility_scope_info {
                             ClearCrossCrate::Set(ref data) => data,
                             ClearCrossCrate::Clear => return None,
                         };
+                        let dir = if op == BinOp::Shr {
+                            "right"
+                        } else {
+                            "left"
+                        };
                         let node_id = scope_info[source_info.scope].lint_root;
                         self.tcx.lint_node(
                             ::rustc::lint::builtin::EXCEEDING_BITSHIFTS,
                             node_id,
                             span,
-                            "bitshift exceeds the type's number of bits");
+                            &format!("attempt to shift {} with overflow", dir));
                         return None;
                     }
                 }
@@ -334,6 +403,7 @@ impl<'tcx> Visitor<'tcx> for CanConstProp {
             Copy | Move |
             StorageDead | StorageLive |
             Validate |
+            Projection(_) |
             Inspect => {},
             _ => self.can_const_prop[local] = false,
         }
@@ -364,6 +434,7 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
                 .to_ty(self.tcx);
             if let Some(value) = self.const_prop(rval, place_ty, statement.source_info) {
                 if let Place::Local(local) = *place {
+                    trace!("checking whether {:?} can be stored to {:?}", value, local);
                     if self.can_const_prop[local] {
                         trace!("storing {:?} to {:?}", value, local);
                         assert!(self.places[local].is_none());
@@ -384,7 +455,22 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
         self.super_terminator_kind(block, kind, location);
         if let TerminatorKind::Assert { expected, msg, cond, .. } = kind {
             if let Some(value) = self.eval_operand(cond) {
+                trace!("assertion on {:?} should be {:?}", value, expected);
                 if Value::ByVal(PrimVal::from_bool(*expected)) != value.0 {
+                    // poison all places this operand references so that further code
+                    // doesn't use the invalid value
+                    match cond {
+                        Operand::Move(ref place) | Operand::Copy(ref place) => {
+                            let mut place = place;
+                            while let Place::Projection(ref proj) = *place {
+                                place = &proj.base;
+                            }
+                            if let Place::Local(local) = *place {
+                                self.places[local] = None;
+                            }
+                        },
+                        Operand::Constant(_) => {}
+                    }
                     let span = self.mir[block]
                         .terminator
                         .as_ref()
@@ -396,21 +482,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");
-                    let mut lint = self.tcx.struct_span_lint_node(
-                        ::rustc::lint::builtin::CONST_ERR,
-                        node_id,
-                        span,
-                        "constant evaluation error",
-                    );
                     use rustc::mir::AssertMessage::*;
-                    match msg {
+                    let msg = match msg {
                         // Need proper const propagator for these
                         GeneratorResumedAfterReturn |
-                        GeneratorResumedAfterPanic => {
-                            lint.cancel();
-                            return;
-                        },
-                        Math(ref err) => lint.span_label(span, err.description()),
+                        GeneratorResumedAfterPanic => return,
+                        Math(ref err) => err.description().to_owned(),
                         BoundsCheck { ref len, ref index } => {
                             let len = self.eval_operand(len).expect("len must be const");
                             let len = match len.0 {
@@ -424,17 +501,20 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
                                 Value::ByVal(PrimVal::Bytes(n)) => n,
                                 _ => bug!("const index not primitive: {:?}", index),
                             };
-                            lint.span_label(
-                                span,
-                                format!(
-                                    "index out of bounds: \
-                                    the len is {} but the index is {}",
-                                    len,
-                                    index,
-                                ),
+                            format!(
+                                "index out of bounds: \
+                                the len is {} but the index is {}",
+                                len,
+                                index,
                             )
                         },
-                    }.emit();
+                    };
+                    self.tcx.lint_node(
+                        ::rustc::lint::builtin::CONST_ERR,
+                        node_id,
+                        span,
+                        &msg,
+                    );
                 }
             }
         }
diff --git a/src/test/compile-fail/const-err-early.rs b/src/test/compile-fail/const-err-early.rs
index 53077d74ce5..3de0f1ff61e 100644
--- a/src/test/compile-fail/const-err-early.rs
+++ b/src/test/compile-fail/const-err-early.rs
@@ -11,11 +11,14 @@
 #![deny(const_err)]
 
 pub const A: i8 = -std::i8::MIN; //~ ERROR E0080
-//~| ERROR const_err
-//~| ERROR const_err
+//~^ ERROR attempt to negate with overflow
+//~| ERROR constant evaluation error
 pub const B: u8 = 200u8 + 200u8; //~ ERROR E0080
+//~^ ERROR attempt to add with overflow
 pub const C: u8 = 200u8 * 4; //~ ERROR E0080
+//~^ ERROR attempt to multiply with overflow
 pub const D: u8 = 42u8 - (42u8 + 1); //~ ERROR E0080
+//~^ ERROR attempt to subtract with overflow
 pub const E: u8 = [5u8][1];
 //~^ ERROR E0080
 
diff --git a/src/test/compile-fail/const-err-multi.rs b/src/test/compile-fail/const-err-multi.rs
index d72097848fe..d2355f57f17 100644
--- a/src/test/compile-fail/const-err-multi.rs
+++ b/src/test/compile-fail/const-err-multi.rs
@@ -12,8 +12,8 @@
 
 pub const A: i8 = -std::i8::MIN;
 //~^ ERROR E0080
-//~| ERROR const_err
-//~| ERROR const_err
+//~| ERROR attempt to negate with overflow
+//~| ERROR constant evaluation error
 pub const B: i8 = A;
 //~^ ERROR E0080
 pub const C: u8 = A as u8;
diff --git a/src/test/compile-fail/const-err2.rs b/src/test/compile-fail/const-err2.rs
index 09983f17926..46b73371e56 100644
--- a/src/test/compile-fail/const-err2.rs
+++ b/src/test/compile-fail/const-err2.rs
@@ -8,6 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// needed because negating int::MIN will behave differently between
+// optimized compilation and unoptimized compilation and thus would
+// lead to different lints being emitted
+// compile-flags: -O
+
 #![feature(rustc_attrs)]
 #![allow(exceeding_bitshifts)]
 #![deny(const_err)]
diff --git a/src/test/compile-fail/const-eval-overflow2.rs b/src/test/compile-fail/const-eval-overflow2.rs
index 25787b7bb4b..a0d8f9672c0 100644
--- a/src/test/compile-fail/const-eval-overflow2.rs
+++ b/src/test/compile-fail/const-eval-overflow2.rs
@@ -25,46 +25,54 @@ const VALS_I8: (i8,) =
     (
      i8::MIN - 1,
      //~^ ERROR constant evaluation error
+     //~| ERROR attempt to subtract with overflow
      );
 
 const VALS_I16: (i16,) =
     (
      i16::MIN - 1,
      //~^ ERROR constant evaluation error
+     //~| ERROR attempt to subtract with overflow
      );
 
 const VALS_I32: (i32,) =
     (
      i32::MIN - 1,
      //~^ ERROR constant evaluation error
+     //~| ERROR attempt to subtract with overflow
      );
 
 const VALS_I64: (i64,) =
     (
      i64::MIN - 1,
      //~^ ERROR constant evaluation error
+     //~| ERROR attempt to subtract with overflow
      );
 
 const VALS_U8: (u8,) =
     (
      u8::MIN - 1,
      //~^ ERROR constant evaluation error
+     //~| ERROR attempt to subtract with overflow
      );
 
 const VALS_U16: (u16,) = (
      u16::MIN - 1,
      //~^ ERROR constant evaluation error
+     //~| ERROR attempt to subtract with overflow
      );
 
 const VALS_U32: (u32,) = (
      u32::MIN - 1,
      //~^ ERROR constant evaluation error
+     //~| ERROR attempt to subtract with overflow
      );
 
 const VALS_U64: (u64,) =
     (
      u64::MIN - 1,
      //~^ ERROR constant evaluation error
+     //~| ERROR attempt to subtract with overflow
      );
 
 fn main() {
diff --git a/src/test/compile-fail/const-eval-overflow2b.rs b/src/test/compile-fail/const-eval-overflow2b.rs
index d8332757b64..08128f90e53 100644
--- a/src/test/compile-fail/const-eval-overflow2b.rs
+++ b/src/test/compile-fail/const-eval-overflow2b.rs
@@ -25,46 +25,54 @@ const VALS_I8: (i8,) =
     (
      i8::MAX + 1,
      //~^ ERROR constant evaluation error
+     //~| ERROR attempt to add with overflow
      );
 
 const VALS_I16: (i16,) =
     (
      i16::MAX + 1,
      //~^ ERROR constant evaluation error
+     //~| ERROR attempt to add with overflow
      );
 
 const VALS_I32: (i32,) =
     (
      i32::MAX + 1,
      //~^ ERROR constant evaluation error
+     //~| ERROR attempt to add with overflow
      );
 
 const VALS_I64: (i64,) =
     (
      i64::MAX + 1,
      //~^ ERROR constant evaluation error
+     //~| ERROR attempt to add with overflow
      );
 
 const VALS_U8: (u8,) =
     (
      u8::MAX + 1,
      //~^ ERROR constant evaluation error
+     //~| ERROR attempt to add with overflow
      );
 
 const VALS_U16: (u16,) = (
      u16::MAX + 1,
      //~^ ERROR constant evaluation error
+     //~| ERROR attempt to add with overflow
      );
 
 const VALS_U32: (u32,) = (
      u32::MAX + 1,
      //~^ ERROR constant evaluation error
+     //~| ERROR attempt to add with overflow
      );
 
 const VALS_U64: (u64,) =
     (
      u64::MAX + 1,
      //~^ ERROR constant evaluation error
+     //~| ERROR attempt to add with overflow
      );
 
 fn main() {
diff --git a/src/test/compile-fail/const-eval-overflow2c.rs b/src/test/compile-fail/const-eval-overflow2c.rs
index 2a8e4dc2c34..31a1638cade 100644
--- a/src/test/compile-fail/const-eval-overflow2c.rs
+++ b/src/test/compile-fail/const-eval-overflow2c.rs
@@ -25,46 +25,54 @@ const VALS_I8: (i8,) =
     (
      i8::MIN * 2,
      //~^ ERROR constant evaluation error
+     //~| ERROR attempt to multiply with overflow
      );
 
 const VALS_I16: (i16,) =
     (
      i16::MIN * 2,
      //~^ ERROR constant evaluation error
+     //~| ERROR attempt to multiply with overflow
      );
 
 const VALS_I32: (i32,) =
     (
      i32::MIN * 2,
      //~^ ERROR constant evaluation error
+     //~| ERROR attempt to multiply with overflow
      );
 
 const VALS_I64: (i64,) =
     (
      i64::MIN * 2,
      //~^ ERROR constant evaluation error
+     //~| ERROR attempt to multiply with overflow
      );
 
 const VALS_U8: (u8,) =
     (
      u8::MAX * 2,
      //~^ ERROR constant evaluation error
+     //~| ERROR attempt to multiply with overflow
      );
 
 const VALS_U16: (u16,) = (
      u16::MAX * 2,
      //~^ ERROR constant evaluation error
+     //~| ERROR attempt to multiply with overflow
      );
 
 const VALS_U32: (u32,) = (
      u32::MAX * 2,
      //~^ ERROR constant evaluation error
+     //~| ERROR attempt to multiply with overflow
      );
 
 const VALS_U64: (u64,) =
     (
      u64::MAX * 2,
      //~^ ERROR constant evaluation error
+     //~| ERROR attempt to multiply with overflow
      );
 
 fn main() {
diff --git a/src/test/compile-fail/eval-enum.rs b/src/test/compile-fail/eval-enum.rs
index 469618407d8..49f76c532df 100644
--- a/src/test/compile-fail/eval-enum.rs
+++ b/src/test/compile-fail/eval-enum.rs
@@ -13,12 +13,10 @@ enum Test {
     //~^ attempt to divide by zero
     //~| ERROR constant evaluation error
     //~| WARN constant evaluation error
-    //~| WARN constant evaluation error
     RemZero = 1%0,
     //~^ attempt to calculate the remainder with a divisor of zero
     //~| ERROR constant evaluation error
     //~| WARN constant evaluation error
-    //~| WARN constant evaluation error
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/issue-44578.rs b/src/test/compile-fail/issue-44578.rs
index 9efe3d90a93..18cfb35113d 100644
--- a/src/test/compile-fail/issue-44578.rs
+++ b/src/test/compile-fail/issue-44578.rs
@@ -18,7 +18,7 @@ enum Bar<A, B> {
 }
 
 impl<A: Foo, B: Foo> Foo for Bar<A, B> {
-    const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize]; //~ E0080
+    const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize];
 }
 
 impl Foo for u8 {
diff --git a/src/test/compile-fail/issue-8460-const.rs b/src/test/compile-fail/issue-8460-const.rs
index 024aca2e66d..1d59e75a0f0 100644
--- a/src/test/compile-fail/issue-8460-const.rs
+++ b/src/test/compile-fail/issue-8460-const.rs
@@ -9,110 +9,69 @@
 // except according to those terms.
 
 #![deny(const_err)]
-//~^ NOTE lint level defined here
 
 use std::{isize, i8, i16, i32, i64};
 use std::thread;
 
 fn main() {
     assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
-    //~^ NOTE attempt to divide with overflow
-    //~| NOTE attempted to do overflowing math
-    //~| ERROR constant evaluation error
+    //~^ ERROR attempt to divide with overflow
     //~| ERROR constant evaluation error
     assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err());
-    //~^ NOTE attempt to divide with overflow
-    //~| NOTE attempted to do overflowing math
-    //~| ERROR constant evaluation error
+    //~^ ERROR attempt to divide with overflow
     //~| ERROR constant evaluation error
     assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err());
-    //~^ NOTE attempt to divide with overflow
-    //~| NOTE attempted to do overflowing math
-    //~| ERROR constant evaluation error
+    //~^ ERROR attempt to divide with overflow
     //~| ERROR constant evaluation error
     assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err());
-    //~^ NOTE attempt to divide with overflow
-    //~| NOTE attempted to do overflowing math
-    //~| ERROR constant evaluation error
+    //~^ ERROR attempt to divide with overflow
     //~| ERROR constant evaluation error
     assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err());
-    //~^ NOTE attempt to divide with overflow
-    //~| NOTE attempted to do overflowing math
-    //~| ERROR constant evaluation error
+    //~^ ERROR attempt to divide with overflow
     //~| ERROR constant evaluation error
     assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err());
-    //~^ NOTE attempt to divide by zero
-    //~| NOTE attempted to do overflowing math
-    //~| ERROR constant evaluation error
+    //~^ ERROR attempt to divide by zero
     //~| ERROR constant evaluation error
     assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err());
-    //~^ NOTE attempt to divide by zero
-    //~| NOTE attempted to do overflowing math
-    //~| ERROR constant evaluation error
+    //~^ ERROR attempt to divide by zero
     //~| ERROR constant evaluation error
     assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err());
-    //~^ NOTE attempt to divide by zero
-    //~| NOTE attempted to do overflowing math
-    //~| ERROR constant evaluation error
+    //~^ ERROR attempt to divide by zero
     //~| ERROR constant evaluation error
     assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err());
-    //~^ NOTE attempt to divide by zero
-    //~| NOTE attempted to do overflowing math
-    //~| ERROR constant evaluation error
+    //~^ ERROR attempt to divide by zero
     //~| ERROR constant evaluation error
     assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err());
-    //~^ NOTE attempt to divide by zero
-    //~| NOTE attempted to do overflowing math
-    //~| ERROR constant evaluation error
+    //~^ ERROR attempt to divide by zero
     //~| ERROR constant evaluation error
     assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
-    //~^ NOTE attempt to calculate the remainder with overflow
-    //~| NOTE attempted to do overflowing math
-    //~| ERROR constant evaluation error
+    //~^ ERROR attempt to calculate the remainder with overflow
     //~| ERROR constant evaluation error
     assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
-    //~^ NOTE attempt to calculate the remainder with overflow
-    //~| NOTE attempted to do overflowing math
-    //~| ERROR constant evaluation error
+    //~^ ERROR attempt to calculate the remainder with overflow
     //~| ERROR constant evaluation error
     assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
-    //~^ NOTE attempt to calculate the remainder with overflow
-    //~| NOTE attempted to do overflowing math
-    //~| ERROR constant evaluation error
+    //~^ ERROR attempt to calculate the remainder with overflow
     //~| ERROR constant evaluation error
     assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
-    //~^ NOTE attempt to calculate the remainder with overflow
-    //~| NOTE attempted to do overflowing math
-    //~| ERROR constant evaluation error
+    //~^ ERROR attempt to calculate the remainder with overflow
     //~| ERROR constant evaluation error
     assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
-    //~^ NOTE attempt to calculate the remainder with overflow
-    //~| NOTE attempted to do overflowing math
-    //~| ERROR constant evaluation error
+    //~^ ERROR attempt to calculate the remainder with overflow
     //~| ERROR constant evaluation error
     assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err());
-    //~^ NOTE attempt to calculate the remainder with a divisor of zero
-    //~| NOTE attempted to do overflowing math
-    //~| ERROR constant evaluation error
+    //~^ ERROR attempt to calculate the remainder with a divisor of zero
     //~| ERROR constant evaluation error
     assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err());
-    //~^ NOTE attempt to calculate the remainder with a divisor of zero
-    //~| NOTE attempted to do overflowing math
-    //~| ERROR constant evaluation error
+    //~^ ERROR attempt to calculate the remainder with a divisor of zero
     //~| ERROR constant evaluation error
     assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err());
-    //~^ NOTE attempt to calculate the remainder with a divisor of zero
-    //~| NOTE attempted to do overflowing math
-    //~| ERROR constant evaluation error
+    //~^ ERROR attempt to calculate the remainder with a divisor of zero
     //~| ERROR constant evaluation error
     assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err());
-    //~^ NOTE attempt to calculate the remainder with a divisor of zero
-    //~| NOTE attempted to do overflowing math
-    //~| ERROR constant evaluation error
+    //~^ ERROR attempt to calculate the remainder with a divisor of zero
     //~| ERROR constant evaluation error
     assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err());
-    //~^ NOTE attempt to calculate the remainder with a divisor of zero
-    //~| NOTE attempted to do overflowing math
-    //~| ERROR constant evaluation error
+    //~^ ERROR attempt to calculate the remainder with a divisor of zero
     //~| ERROR constant evaluation error
 }
diff --git a/src/test/compile-fail/lint-exceeding-bitshifts.rs b/src/test/compile-fail/lint-exceeding-bitshifts.rs
index 34b43c5badb..5ebfcc4926b 100644
--- a/src/test/compile-fail/lint-exceeding-bitshifts.rs
+++ b/src/test/compile-fail/lint-exceeding-bitshifts.rs
@@ -8,50 +8,50 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![deny(exceeding_bitshifts)]
+#![deny(exceeding_bitshifts, const_err)]
 #![allow(unused_variables)]
-#![allow(dead_code, const_err)]
+#![allow(dead_code)]
 
 fn main() {
       let n = 1u8 << 7;
-      let n = 1u8 << 8;   //~ ERROR: bitshift exceeds the type's number of bits
+      let n = 1u8 << 8;   //~ ERROR: attempt to shift left with overflow
       let n = 1u16 << 15;
-      let n = 1u16 << 16; //~ ERROR: bitshift exceeds the type's number of bits
+      let n = 1u16 << 16; //~ ERROR: attempt to shift left with overflow
       let n = 1u32 << 31;
-      let n = 1u32 << 32; //~ ERROR: bitshift exceeds the type's number of bits
+      let n = 1u32 << 32; //~ ERROR: attempt to shift left with overflow
       let n = 1u64 << 63;
-      let n = 1u64 << 64; //~ ERROR: bitshift exceeds the type's number of bits
+      let n = 1u64 << 64; //~ ERROR: attempt to shift left with overflow
       let n = 1i8 << 7;
-      let n = 1i8 << 8;   //~ ERROR: bitshift exceeds the type's number of bits
+      let n = 1i8 << 8;   //~ ERROR: attempt to shift left with overflow
       let n = 1i16 << 15;
-      let n = 1i16 << 16; //~ ERROR: bitshift exceeds the type's number of bits
+      let n = 1i16 << 16; //~ ERROR: attempt to shift left with overflow
       let n = 1i32 << 31;
-      let n = 1i32 << 32; //~ ERROR: bitshift exceeds the type's number of bits
+      let n = 1i32 << 32; //~ ERROR: attempt to shift left with overflow
       let n = 1i64 << 63;
-      let n = 1i64 << 64; //~ ERROR: bitshift exceeds the type's number of bits
+      let n = 1i64 << 64; //~ ERROR: attempt to shift left with overflow
 
       let n = 1u8 >> 7;
-      let n = 1u8 >> 8;   //~ ERROR: bitshift exceeds the type's number of bits
+      let n = 1u8 >> 8;   //~ ERROR: attempt to shift right with overflow
       let n = 1u16 >> 15;
-      let n = 1u16 >> 16; //~ ERROR: bitshift exceeds the type's number of bits
+      let n = 1u16 >> 16; //~ ERROR: attempt to shift right with overflow
       let n = 1u32 >> 31;
-      let n = 1u32 >> 32; //~ ERROR: bitshift exceeds the type's number of bits
+      let n = 1u32 >> 32; //~ ERROR: attempt to shift right with overflow
       let n = 1u64 >> 63;
-      let n = 1u64 >> 64; //~ ERROR: bitshift exceeds the type's number of bits
+      let n = 1u64 >> 64; //~ ERROR: attempt to shift right with overflow
       let n = 1i8 >> 7;
-      let n = 1i8 >> 8;   //~ ERROR: bitshift exceeds the type's number of bits
+      let n = 1i8 >> 8;   //~ ERROR: attempt to shift right with overflow
       let n = 1i16 >> 15;
-      let n = 1i16 >> 16; //~ ERROR: bitshift exceeds the type's number of bits
+      let n = 1i16 >> 16; //~ ERROR: attempt to shift right with overflow
       let n = 1i32 >> 31;
-      let n = 1i32 >> 32; //~ ERROR: bitshift exceeds the type's number of bits
+      let n = 1i32 >> 32; //~ ERROR: attempt to shift right with overflow
       let n = 1i64 >> 63;
-      let n = 1i64 >> 64; //~ ERROR: bitshift exceeds the type's number of bits
+      let n = 1i64 >> 64; //~ ERROR: attempt to shift right with overflow
 
       let n = 1u8;
       let n = n << 7;
-      let n = n << 8; //~ ERROR: bitshift exceeds the type's number of bits
+      let n = n << 8; //~ ERROR: attempt to shift left with overflow
 
-      let n = 1u8 << -8; //~ ERROR: bitshift exceeds the type's number of bits
+      let n = 1u8 << -8; //~ ERROR: attempt to shift left with overflow
 
       let n = 1i8<<(1isize+-1);
 }
diff --git a/src/test/compile-fail/lint-exceeding-bitshifts2.rs b/src/test/compile-fail/lint-exceeding-bitshifts2.rs
index a8027034fbe..3ba300eb7c4 100644
--- a/src/test/compile-fail/lint-exceeding-bitshifts2.rs
+++ b/src/test/compile-fail/lint-exceeding-bitshifts2.rs
@@ -14,7 +14,7 @@
 
 fn main() {
       let n = 1u8 << (4+3);
-      let n = 1u8 << (4+4); //~ ERROR: bitshift exceeds
+      let n = 1u8 << (4+4); //~ ERROR: attempt to shift left with overflow
       let n = 1i64 >> [63][0];
       let n = 1i64 >> [64][0]; // should be linting, needs to wait for const propagation
 
@@ -22,6 +22,6 @@ fn main() {
       const BITS: usize = 32;
       #[cfg(target_pointer_width = "64")]
       const BITS: usize = 64;
-      let n = 1_isize << BITS; //~ ERROR: bitshift exceeds
-      let n = 1_usize << BITS; //~ ERROR: bitshift exceeds
+      let n = 1_isize << BITS; //~ ERROR: attempt to shift left with overflow
+      let n = 1_usize << BITS; //~ ERROR: attempt to shift left with overflow
 }
diff --git a/src/test/ui/const-eval-overflow-4.rs b/src/test/ui/const-eval-overflow-4.rs
index a1b90f623cd..24e178152ee 100644
--- a/src/test/ui/const-eval-overflow-4.rs
+++ b/src/test/ui/const-eval-overflow-4.rs
@@ -22,6 +22,7 @@ use std::{u8, u16, u32, u64, usize};
 const A_I8_T
     : [u32; (i8::MAX as i8 + 1i8) as usize]
     //~^ ERROR E0080
+    //~| WARN attempt to add with overflow
     = [0; (i8::MAX as usize) + 1];
 
 fn main() {
diff --git a/src/test/ui/const-eval-overflow-4.stderr b/src/test/ui/const-eval-overflow-4.stderr
index e967f024ae3..14753038fef 100644
--- a/src/test/ui/const-eval-overflow-4.stderr
+++ b/src/test/ui/const-eval-overflow-4.stderr
@@ -1,3 +1,11 @@
+warning: attempt to add with overflow
+  --> $DIR/const-eval-overflow-4.rs:23:13
+   |
+LL |     : [u32; (i8::MAX as i8 + 1i8) as usize]
+   |             ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: #[warn(const_err)] on by default
+
 error[E0080]: constant evaluation error
   --> $DIR/const-eval-overflow-4.rs:23:13
    |
diff --git a/src/test/ui/const-eval/conditional_array_execution.rs b/src/test/ui/const-eval/conditional_array_execution.rs
index 41ceb609df5..324bcf60e8f 100644
--- a/src/test/ui/const-eval/conditional_array_execution.rs
+++ b/src/test/ui/const-eval/conditional_array_execution.rs
@@ -10,7 +10,8 @@
 
 const X: u32 = 5;
 const Y: u32 = 6;
-const FOO: u32 = [X - Y, Y - X][(X < Y) as usize]; //~ E0080
+const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
+//~^ WARN attempt to subtract with overflow
 
 fn main() {
     println!("{}", FOO); //~ E0080
diff --git a/src/test/ui/const-eval/conditional_array_execution.stderr b/src/test/ui/const-eval/conditional_array_execution.stderr
index 8d421f401ca..4cf12e22283 100644
--- a/src/test/ui/const-eval/conditional_array_execution.stderr
+++ b/src/test/ui/const-eval/conditional_array_execution.stderr
@@ -1,15 +1,17 @@
-error[E0080]: constant evaluation error
-  --> $DIR/conditional_array_execution.rs:16:20
+warning: attempt to subtract with overflow
+  --> $DIR/conditional_array_execution.rs:13:19
    |
-LL |     println!("{}", FOO); //~ E0080
-   |                    ^^^ referenced constant has errors
+LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
+   |                   ^^^^^
+   |
+   = note: #[warn(const_err)] on by default
 
 error[E0080]: constant evaluation error
-  --> $DIR/conditional_array_execution.rs:13:19
+  --> $DIR/conditional_array_execution.rs:17:20
    |
-LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize]; //~ E0080
-   |                   ^^^^^ attempt to subtract with overflow
+LL |     println!("{}", FOO); //~ E0080
+   |                    ^^^ referenced constant has errors
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 If you want more information on this error, try using "rustc --explain E0080"
diff --git a/src/test/ui/const-eval/issue-43197.rs b/src/test/ui/const-eval/issue-43197.rs
index e87b2caa49f..d5c4796d0b4 100644
--- a/src/test/ui/const-eval/issue-43197.rs
+++ b/src/test/ui/const-eval/issue-43197.rs
@@ -15,8 +15,10 @@ const fn foo(x: u32) -> u32 {
 }
 
 fn main() {
-    const X: u32 = 0-1; //~ ERROR constant evaluation error
-    const Y: u32 = foo(0-1); //~ ERROR constant evaluation error
+    const X: u32 = 0-1;
+    //~^ WARN attempt to subtract with overflow
+    const Y: u32 = foo(0-1);
+    //~^ WARN attempt to subtract with overflow
     println!("{} {}", X, Y);
     //~^ ERROR constant evaluation error
     //~| ERROR constant evaluation error
diff --git a/src/test/ui/const-eval/issue-43197.stderr b/src/test/ui/const-eval/issue-43197.stderr
index 21b9a282c48..3f108268747 100644
--- a/src/test/ui/const-eval/issue-43197.stderr
+++ b/src/test/ui/const-eval/issue-43197.stderr
@@ -1,27 +1,29 @@
-error[E0080]: constant evaluation error
-  --> $DIR/issue-43197.rs:20:23
+warning: attempt to subtract with overflow
+  --> $DIR/issue-43197.rs:18:20
    |
-LL |     println!("{} {}", X, Y);
-   |                       ^ referenced constant has errors
+LL |     const X: u32 = 0-1;
+   |                    ^^^
+   |
+   = note: #[warn(const_err)] on by default
 
 error[E0080]: constant evaluation error
-  --> $DIR/issue-43197.rs:20:26
+  --> $DIR/issue-43197.rs:22:23
    |
 LL |     println!("{} {}", X, Y);
-   |                          ^ referenced constant has errors
+   |                       ^ referenced constant has errors
 
-error[E0080]: constant evaluation error
-  --> $DIR/issue-43197.rs:19:24
+warning: attempt to subtract with overflow
+  --> $DIR/issue-43197.rs:20:24
    |
-LL |     const Y: u32 = foo(0-1); //~ ERROR constant evaluation error
-   |                        ^^^ attempt to subtract with overflow
+LL |     const Y: u32 = foo(0-1);
+   |                        ^^^
 
 error[E0080]: constant evaluation error
-  --> $DIR/issue-43197.rs:18:20
+  --> $DIR/issue-43197.rs:22:26
    |
-LL |     const X: u32 = 0-1; //~ ERROR constant evaluation error
-   |                    ^^^ attempt to subtract with overflow
+LL |     println!("{} {}", X, Y);
+   |                          ^ referenced constant has errors
 
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
 If you want more information on this error, try using "rustc --explain E0080"
diff --git a/src/test/ui/const-eval/pub_const_err.rs b/src/test/ui/const-eval/pub_const_err.rs
new file mode 100644
index 00000000000..bdb9f5b19a8
--- /dev/null
+++ b/src/test/ui/const-eval/pub_const_err.rs
@@ -0,0 +1,16 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![deny(const_err)]
+
+#![crate_type = "lib"]
+
+pub const Z: u32 = 0 - 1;
+//~^ ERROR attempt to subtract with overflow
diff --git a/src/test/ui/const-eval/pub_const_err.stderr b/src/test/ui/const-eval/pub_const_err.stderr
new file mode 100644
index 00000000000..b77ec38ca16
--- /dev/null
+++ b/src/test/ui/const-eval/pub_const_err.stderr
@@ -0,0 +1,14 @@
+error: attempt to subtract with overflow
+  --> $DIR/pub_const_err.rs:15:20
+   |
+LL | pub const Z: u32 = 0 - 1;
+   |                    ^^^^^
+   |
+note: lint level defined here
+  --> $DIR/pub_const_err.rs:11:9
+   |
+LL | #![deny(const_err)]
+   |         ^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-len-underflow-separate-spans.rs b/src/test/ui/const-len-underflow-separate-spans.rs
index 35e3ba9ce09..ee07dabab1f 100644
--- a/src/test/ui/const-len-underflow-separate-spans.rs
+++ b/src/test/ui/const-len-underflow-separate-spans.rs
@@ -16,6 +16,7 @@ const ONE: usize = 1;
 const TWO: usize = 2;
 const LEN: usize = ONE - TWO;
 //~^ ERROR E0080
+//~| WARN attempt to subtract with overflow
 
 fn main() {
     let a: [i8; LEN] = unimplemented!();
diff --git a/src/test/ui/const-len-underflow-separate-spans.stderr b/src/test/ui/const-len-underflow-separate-spans.stderr
index 301b063885c..98f4ac9e83f 100644
--- a/src/test/ui/const-len-underflow-separate-spans.stderr
+++ b/src/test/ui/const-len-underflow-separate-spans.stderr
@@ -1,3 +1,11 @@
+warning: attempt to subtract with overflow
+  --> $DIR/const-len-underflow-separate-spans.rs:17:20
+   |
+LL | const LEN: usize = ONE - TWO;
+   |                    ^^^^^^^^^
+   |
+   = note: #[warn(const_err)] on by default
+
 error[E0080]: constant evaluation error
   --> $DIR/const-len-underflow-separate-spans.rs:17:20
    |
@@ -5,7 +13,7 @@ LL | const LEN: usize = ONE - TWO;
    |                    ^^^^^^^^^ attempt to subtract with overflow
 
 error[E0080]: constant evaluation error
-  --> $DIR/const-len-underflow-separate-spans.rs:21:17
+  --> $DIR/const-len-underflow-separate-spans.rs:22:17
    |
 LL |     let a: [i8; LEN] = unimplemented!();
    |                 ^^^ referenced constant has errors
diff --git a/src/test/ui/error-codes/E0080.rs b/src/test/ui/error-codes/E0080.rs
index cca63f23b77..c8e42571128 100644
--- a/src/test/ui/error-codes/E0080.rs
+++ b/src/test/ui/error-codes/E0080.rs
@@ -10,7 +10,6 @@
 
 enum Enum {
     X = (1 << 500), //~ ERROR E0080
-    //~| ERROR bitshift exceeds
     //~| shift left with overflow
     Y = (1 / 0) //~ ERROR E0080
     //~| const_err
diff --git a/src/test/ui/error-codes/E0080.stderr b/src/test/ui/error-codes/E0080.stderr
index 501051b9fe6..6db53acd6b9 100644
--- a/src/test/ui/error-codes/E0080.stderr
+++ b/src/test/ui/error-codes/E0080.stderr
@@ -1,4 +1,4 @@
-error: bitshift exceeds the type's number of bits
+error: attempt to shift left with overflow
   --> $DIR/E0080.rs:12:9
    |
 LL |     X = (1 << 500), //~ ERROR E0080
@@ -12,22 +12,22 @@ error[E0080]: constant evaluation error
 LL |     X = (1 << 500), //~ ERROR E0080
    |         ^^^^^^^^^^ attempt to shift left with overflow
 
-warning: constant evaluation error
-  --> $DIR/E0080.rs:15:9
+warning: attempt to divide by zero
+  --> $DIR/E0080.rs:14:9
    |
 LL |     Y = (1 / 0) //~ ERROR E0080
-   |         ^^^^^^^ attempt to divide by zero
+   |         ^^^^^^^
    |
    = note: #[warn(const_err)] on by default
 
 warning: constant evaluation error
-  --> $DIR/E0080.rs:15:9
+  --> $DIR/E0080.rs:14:9
    |
 LL |     Y = (1 / 0) //~ ERROR E0080
    |         ^^^^^^^ attempted to do overflowing math
 
 error[E0080]: constant evaluation error
-  --> $DIR/E0080.rs:15:9
+  --> $DIR/E0080.rs:14:9
    |
 LL |     Y = (1 / 0) //~ ERROR E0080
    |         ^^^^^^^ attempt to divide by zero