about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-06-06 11:17:15 +0000
committerbors <bors@rust-lang.org>2018-06-06 11:17:15 +0000
commit9ac372568b0a63c0abb8953431fa6a392de040a3 (patch)
treed92b896d058959a52902ace421a5be9b5a71dd32 /src
parent685faa2c3ee062aaf30ddf6d3daf4ef3b576979b (diff)
parent14d08e53710f8be52734ad285d221b224415dc15 (diff)
Auto merge of #51316 - oli-obk:const_err, r=nikomatsakis
Refactor the const eval diagnostic API

* no longer report "const eval error" for things that have typeck errors
* errors and lints have saner spans and messages
* unified the diagnostic logic (const eval errors were slightly different depending on where they were reported, and there was also code duplication between the different reporters)
* report errors if an erroneous constant is used inside a promoted (fixes most of #50814)
Diffstat (limited to 'src')
-rw-r--r--src/librustc/ich/impls_ty.rs17
-rw-r--r--src/librustc/lint/context.rs3
-rw-r--r--src/librustc/middle/const_val.rs139
-rw-r--r--src/librustc/mir/interpret/error.rs48
-rw-r--r--src/librustc/traits/error_reporting.rs9
-rw-r--r--src/librustc/traits/fulfill.rs3
-rw-r--r--src/librustc/ty/mod.rs8
-rw-r--r--src/librustc/ty/structural_impls.rs12
-rw-r--r--src/librustc_codegen_llvm/mir/constant.rs5
-rw-r--r--src/librustc_codegen_llvm/mir/operand.rs5
-rw-r--r--src/librustc_lint/builtin.rs19
-rw-r--r--src/librustc_mir/hair/cx/expr.rs2
-rw-r--r--src/librustc_mir/hair/pattern/check_match.rs4
-rw-r--r--src/librustc_mir/hair/pattern/mod.rs5
-rw-r--r--src/librustc_mir/interpret/const_eval.rs51
-rw-r--r--src/librustc_mir/interpret/eval_context.rs100
-rw-r--r--src/librustc_mir/interpret/memory.rs16
-rw-r--r--src/librustc_mir/interpret/mod.rs1
-rw-r--r--src/librustc_mir/monomorphize/collector.rs26
-rw-r--r--src/librustc_mir/transform/const_prop.rs110
-rw-r--r--src/librustc_typeck/check/mod.rs5
-rw-r--r--src/test/compile-fail/const-array-oob.rs2
-rw-r--r--src/test/compile-fail/const-err-early.rs2
-rw-r--r--src/test/compile-fail/const-err-multi.rs5
-rw-r--r--src/test/compile-fail/const-err.rs1
-rw-r--r--src/test/compile-fail/const-integer-bool-ops.rs10
-rw-r--r--src/test/compile-fail/const-len-underflow-subspans.rs2
-rw-r--r--src/test/compile-fail/const-match-check.rs1
-rw-r--r--src/test/compile-fail/const-tup-index-span.rs1
-rw-r--r--src/test/compile-fail/eval-enum.rs8
-rw-r--r--src/test/compile-fail/issue-43105.rs2
-rw-r--r--src/test/compile-fail/issue-8460-const.rs40
-rw-r--r--src/test/ui/const-eval-overflow-2.rs2
-rw-r--r--src/test/ui/const-eval-overflow-2.stderr11
-rw-r--r--src/test/ui/const-eval-overflow-4.rs4
-rw-r--r--src/test/ui/const-eval-overflow-4.stderr15
-rw-r--r--src/test/ui/const-eval/conditional_array_execution.nll.stderr74
-rw-r--r--src/test/ui/const-eval/conditional_array_execution.rs6
-rw-r--r--src/test/ui/const-eval/conditional_array_execution.stderr41
-rw-r--r--src/test/ui/const-eval/index_out_of_bounds.rs1
-rw-r--r--src/test/ui/const-eval/index_out_of_bounds.stderr14
-rw-r--r--src/test/ui/const-eval/issue-43197.nll.stderr118
-rw-r--r--src/test/ui/const-eval/issue-43197.rs11
-rw-r--r--src/test/ui/const-eval/issue-43197.stderr77
-rw-r--r--src/test/ui/const-eval/issue-44578.nll.stderr39
-rw-r--r--src/test/ui/const-eval/issue-44578.rs8
-rw-r--r--src/test/ui/const-eval/issue-44578.stderr26
-rw-r--r--src/test/ui/const-eval/issue-50814-2.rs43
-rw-r--r--src/test/ui/const-eval/issue-50814-2.stderr20
-rw-r--r--src/test/ui/const-eval/issue-50814.rs33
-rw-r--r--src/test/ui/const-eval/issue-50814.stderr20
-rw-r--r--src/test/ui/const-eval/promoted_const_fn_fail.rs4
-rw-r--r--src/test/ui/const-eval/promoted_const_fn_fail.stderr15
-rw-r--r--src/test/ui/const-eval/promoted_errors.stderr8
-rw-r--r--src/test/ui/const-eval/pub_const_err.stderr4
-rw-r--r--src/test/ui/const-eval/pub_const_err_bin.stderr4
-rw-r--r--src/test/ui/const-fn-error.rs3
-rw-r--r--src/test/ui/const-fn-error.stderr18
-rw-r--r--src/test/ui/const-len-underflow-separate-spans.rs1
-rw-r--r--src/test/ui/const-len-underflow-separate-spans.stderr19
-rw-r--r--src/test/ui/error-codes/E0080.stderr6
-rw-r--r--src/test/ui/infinite-recursion-const-fn.rs4
-rw-r--r--src/test/ui/infinite-recursion-const-fn.stderr20
-rw-r--r--src/test/ui/type-dependent-def-issue-49241.rs2
-rw-r--r--src/test/ui/type-dependent-def-issue-49241.stderr11
65 files changed, 882 insertions, 462 deletions
diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs
index 04e57883c77..5e67065d1c1 100644
--- a/src/librustc/ich/impls_ty.rs
+++ b/src/librustc/ich/impls_ty.rs
@@ -510,6 +510,7 @@ impl_stable_hash_for!(struct ::middle::const_val::ConstEvalErr<'tcx> {
 
 impl_stable_hash_for!(struct ::middle::const_val::FrameInfo {
     span,
+    lint_root,
     location
 });
 
@@ -523,21 +524,11 @@ for ::middle::const_val::ErrKind<'gcx> {
         mem::discriminant(self).hash_stable(hcx, hasher);
 
         match *self {
-            NonConstPath |
             TypeckError |
+            CouldNotResolve |
             CheckMatchError => {
                 // nothing to do
             }
-            UnimplementedConstVal(s) => {
-                s.hash_stable(hcx, hasher);
-            }
-            IndexOutOfBounds { len, index } => {
-                len.hash_stable(hcx, hasher);
-                index.hash_stable(hcx, hasher);
-            }
-            LayoutError(ref layout_error) => {
-                layout_error.hash_stable(hcx, hasher);
-            }
             Miri(ref err, ref trace) => {
                 err.hash_stable(hcx, hasher);
                 trace.hash_stable(hcx, hasher);
@@ -608,8 +599,8 @@ for ::mir::interpret::EvalErrorKind<'gcx, O> {
             RemainderByZero |
             DivisionByZero |
             GeneratorResumedAfterReturn |
-            GeneratorResumedAfterPanic |
-            ReferencedConstant => {}
+            GeneratorResumedAfterPanic => {}
+            ReferencedConstant(ref err) => err.hash_stable(hcx, hasher),
             MachineError(ref err) => err.hash_stable(hcx, hasher),
             FunctionPointerTyMismatch(a, b) => {
                 a.hash_stable(hcx, hasher);
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index 381bb161e42..824930a7eb0 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -655,6 +655,9 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> {
         f(self);
         self.param_env = old_param_env;
     }
+    pub fn current_lint_root(&self) -> ast::NodeId {
+        self.last_ast_node_with_lint_attrs
+    }
 }
 
 impl<'a, 'tcx> LayoutOf for &'a LateContext<'a, 'tcx> {
diff --git a/src/librustc/middle/const_val.rs b/src/librustc/middle/const_val.rs
index d7f11670511..88275b3c18c 100644
--- a/src/librustc/middle/const_val.rs
+++ b/src/librustc/middle/const_val.rs
@@ -9,13 +9,15 @@
 // except according to those terms.
 
 use hir::def_id::DefId;
-use ty::{self, TyCtxt, layout};
+use ty;
 use ty::subst::Substs;
+use ty::maps::TyCtxtAt;
 use mir::interpret::ConstValue;
 use errors::DiagnosticBuilder;
 
 use graphviz::IntoCow;
 use syntax_pos::Span;
+use syntax::ast;
 
 use std::borrow::Cow;
 use rustc_data_structures::sync::Lrc;
@@ -28,30 +30,26 @@ pub enum ConstVal<'tcx> {
     Value(ConstValue<'tcx>),
 }
 
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
 pub struct ConstEvalErr<'tcx> {
     pub span: Span,
     pub kind: Lrc<ErrKind<'tcx>>,
 }
 
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
 pub enum ErrKind<'tcx> {
 
-    NonConstPath,
-    UnimplementedConstVal(&'static str),
-    IndexOutOfBounds { len: u64, index: u64 },
-
-    LayoutError(layout::LayoutError<'tcx>),
-
+    CouldNotResolve,
     TypeckError,
     CheckMatchError,
     Miri(::mir::interpret::EvalError<'tcx>, Vec<FrameInfo>),
 }
 
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
 pub struct FrameInfo {
     pub span: Span,
     pub location: String,
+    pub lint_root: Option<ast::NodeId>,
 }
 
 #[derive(Clone, Debug)]
@@ -83,16 +81,7 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
         }
 
         match *self.kind {
-            NonConstPath        => simple!("non-constant path in constant expression"),
-            UnimplementedConstVal(what) =>
-                simple!("unimplemented constant expression: {}", what),
-            IndexOutOfBounds { len, index } => {
-                simple!("index out of bounds: the len is {} but the index is {}",
-                        len, index)
-            }
-
-            LayoutError(ref err) => Simple(err.to_string().into_cow()),
-
+            CouldNotResolve => simple!("could not resolve"),
             TypeckError => simple!("type-checking failed"),
             CheckMatchError => simple!("match-checking failed"),
             Miri(ref err, ref trace) => Backtrace(err, trace),
@@ -100,64 +89,90 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
     }
 
     pub fn struct_error(&self,
-        tcx: TyCtxt<'a, 'gcx, 'tcx>,
-        primary_span: Span,
-        primary_kind: &str)
-        -> DiagnosticBuilder<'gcx>
+        tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
+        message: &str)
+        -> Option<DiagnosticBuilder<'tcx>>
     {
-        let mut diag = struct_error(tcx, self.span, "constant evaluation error");
-        self.note(tcx, primary_span, primary_kind, &mut diag);
-        diag
+        self.struct_generic(tcx, message, None, true)
     }
 
-    pub fn note(&self,
-        _tcx: TyCtxt<'a, 'gcx, 'tcx>,
-        primary_span: Span,
-        primary_kind: &str,
-        diag: &mut DiagnosticBuilder)
-    {
-        match self.description() {
-            ConstEvalErrDescription::Simple(message) => {
-                diag.span_label(self.span, message);
-            }
-            ConstEvalErrDescription::Backtrace(miri, frames) => {
-                diag.span_label(self.span, format!("{}", miri));
-                for frame in frames {
-                    diag.span_label(frame.span, format!("inside call to `{}`", frame.location));
-                }
-            }
+    pub fn report_as_error(&self,
+        tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
+        message: &str
+    ) {
+        let err = self.struct_generic(tcx, message, None, true);
+        if let Some(mut err) = err {
+            err.emit();
         }
+    }
 
-        if !primary_span.contains(self.span) {
-            diag.span_note(primary_span,
-                        &format!("for {} here", primary_kind));
+    pub fn report_as_lint(&self,
+        tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
+        message: &str,
+        lint_root: ast::NodeId,
+    ) {
+        let lint = self.struct_generic(
+            tcx,
+            message,
+            Some(lint_root),
+            false,
+        );
+        if let Some(mut lint) = lint {
+            lint.emit();
         }
     }
 
-    pub fn report(&self,
-        tcx: TyCtxt<'a, 'gcx, 'tcx>,
-        primary_span: Span,
-        primary_kind: &str)
-    {
-        match *self.kind {
-            ErrKind::TypeckError | ErrKind::CheckMatchError => return,
-            ErrKind::Miri(ref miri, _) => {
+    fn struct_generic(
+        &self,
+        tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
+        message: &str,
+        lint_root: Option<ast::NodeId>,
+        as_err: bool,
+    ) -> Option<DiagnosticBuilder<'tcx>> {
+        let (msg, frames): (_, &[_]) = match *self.kind {
+            ErrKind::TypeckError | ErrKind::CheckMatchError => return None,
+            ErrKind::Miri(ref miri, ref frames) => {
                 match miri.kind {
                     ::mir::interpret::EvalErrorKind::TypeckError |
-                    ::mir::interpret::EvalErrorKind::Layout(_) => return,
-                    _ => {},
+                    ::mir::interpret::EvalErrorKind::Layout(_) => return None,
+                    ::mir::interpret::EvalErrorKind::ReferencedConstant(ref inner) => {
+                        inner.struct_generic(tcx, "referenced constant", lint_root, as_err)?.emit();
+                        (miri.to_string(), frames)
+                    },
+                    _ => (miri.to_string(), frames),
                 }
             }
-            _ => {}
+            _ => (self.description().into_oneline().to_string(), &[]),
+        };
+        trace!("reporting const eval failure at {:?}", self.span);
+        let mut err = if as_err {
+            struct_error(tcx, message)
+        } else {
+            let node_id = frames
+                .iter()
+                .rev()
+                .filter_map(|frame| frame.lint_root)
+                .next()
+                .or(lint_root)
+                .expect("some part of a failing const eval must be local");
+            tcx.struct_span_lint_node(
+                ::rustc::lint::builtin::CONST_ERR,
+                node_id,
+                tcx.span,
+                message,
+            )
+        };
+        err.span_label(self.span, msg);
+        for FrameInfo { span, location, .. } in frames {
+            err.span_label(*span, format!("inside call to `{}`", location));
         }
-        self.struct_error(tcx, primary_span, primary_kind).emit();
+        Some(err)
     }
 }
 
 pub fn struct_error<'a, 'gcx, 'tcx>(
-    tcx: TyCtxt<'a, 'gcx, 'tcx>,
-    span: Span,
+    tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
     msg: &str,
-) -> DiagnosticBuilder<'gcx> {
-    struct_span_err!(tcx.sess, span, E0080, "{}", msg)
+) -> DiagnosticBuilder<'tcx> {
+    struct_span_err!(tcx.sess, tcx.span, E0080, "{}", msg)
 }
diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs
index 45819afca3f..bf5bae6b20c 100644
--- a/src/librustc/mir/interpret/error.rs
+++ b/src/librustc/mir/interpret/error.rs
@@ -1,6 +1,7 @@
 use std::{fmt, env};
 
 use mir;
+use middle::const_val::ConstEvalErr;
 use ty::{FnSig, Ty, layout};
 use ty::layout::{Size, Align};
 
@@ -10,21 +11,50 @@ use super::{
 
 use backtrace::Backtrace;
 
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, RustcEncodable, RustcDecodable)]
 pub struct EvalError<'tcx> {
     pub kind: EvalErrorKind<'tcx, u64>,
-    pub backtrace: Option<Backtrace>,
 }
 
 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
-        };
+        match env::var("MIRI_BACKTRACE") {
+            Ok(ref val) if !val.is_empty() => {
+                let backtrace = Backtrace::new();
+
+                use std::fmt::Write;
+                let mut trace_text = "\n\nAn error occurred in miri:\n".to_string();
+                write!(trace_text, "backtrace frames: {}\n", backtrace.frames().len()).unwrap();
+                'frames: for (i, frame) in backtrace.frames().iter().enumerate() {
+                    if frame.symbols().is_empty() {
+                        write!(trace_text, "{}: no symbols\n", i).unwrap();
+                    }
+                    for symbol in frame.symbols() {
+                        write!(trace_text, "{}: ", i).unwrap();
+                        if let Some(name) = symbol.name() {
+                            write!(trace_text, "{}\n", name).unwrap();
+                        } else {
+                            write!(trace_text, "<unknown>\n").unwrap();
+                        }
+                        write!(trace_text, "\tat ").unwrap();
+                        if let Some(file_path) = symbol.filename() {
+                            write!(trace_text, "{}", file_path.display()).unwrap();
+                        } else {
+                            write!(trace_text, "<unknown_file>").unwrap();
+                        }
+                        if let Some(line) = symbol.lineno() {
+                            write!(trace_text, ":{}\n", line).unwrap();
+                        } else {
+                            write!(trace_text, "\n").unwrap();
+                        }
+                    }
+                }
+                error!("{}", trace_text);
+            },
+            _ => {},
+        }
         EvalError {
             kind,
-            backtrace,
         }
     }
 }
@@ -122,7 +152,7 @@ pub enum EvalErrorKind<'tcx, O> {
     TypeckError,
     /// Cannot compute this constant because it depends on another one
     /// which already produced an error
-    ReferencedConstant,
+    ReferencedConstant(ConstEvalErr<'tcx>),
     GeneratorResumedAfterReturn,
     GeneratorResumedAfterPanic,
 }
@@ -238,7 +268,7 @@ impl<'tcx, O> EvalErrorKind<'tcx, O> {
                 "there were unresolved type arguments during trait selection",
             TypeckError =>
                 "encountered constants with type errors, stopping evaluation",
-            ReferencedConstant =>
+            ReferencedConstant(_) =>
                 "referenced constant has errors",
             Overflow(mir::BinOp::Add) => "attempt to add with overflow",
             Overflow(mir::BinOp::Sub) => "attempt to subtract with overflow",
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index dc4233436c6..f76b312ee53 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -827,10 +827,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
             }
 
             ConstEvalFailure(ref err) => {
-                if let ::middle::const_val::ErrKind::TypeckError = *err.kind {
-                    return;
+                match err.struct_error(
+                    self.tcx.at(span),
+                    "could not evaluate constant expression",
+                ) {
+                    Some(err) => err,
+                    None => return,
                 }
-                err.struct_error(self.tcx, span, "constant expression")
             }
 
             Overflow => {
diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs
index 4447a2b6ed1..dff89f3c888 100644
--- a/src/librustc/traits/fulfill.rs
+++ b/src/librustc/traits/fulfill.rs
@@ -534,8 +534,7 @@ fn process_predicate<'a, 'gcx, 'tcx>(
                             } else {
                                 Err(CodeSelectionError(ConstEvalFailure(ConstEvalErr {
                                     span: obligation.cause.span,
-                                    kind: ErrKind::UnimplementedConstVal("could not resolve")
-                                        .into(),
+                                    kind: ErrKind::CouldNotResolve.into(),
                                 })))
                             }
                         },
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 0bb0208e2a1..f947ed45686 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -2075,15 +2075,17 @@ impl<'a, 'gcx, 'tcx> AdtDef {
                 } else {
                     info!("invalid enum discriminant: {:#?}", val);
                     ::middle::const_val::struct_error(
-                        tcx,
-                        tcx.def_span(expr_did),
+                        tcx.at(tcx.def_span(expr_did)),
                         "constant evaluation of enum discriminant resulted in non-integer",
                     ).emit();
                     None
                 }
             }
             Err(err) => {
-                err.report(tcx, tcx.def_span(expr_did), "enum discriminant");
+                err.report_as_error(
+                    tcx.at(tcx.def_span(expr_did)),
+                    "could not evaluate enum discriminant",
+                );
                 if !expr_did.is_local() {
                     span_bug!(tcx.def_span(expr_did),
                         "variant discriminant evaluation succeeded \
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index e77ede72143..79a63111850 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -476,7 +476,6 @@ impl<'a, 'tcx> Lift<'tcx> for interpret::EvalError<'a> {
     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(),
         })
     }
 }
@@ -578,7 +577,7 @@ impl<'a, 'tcx, O: Lift<'tcx>> Lift<'tcx> for interpret::EvalErrorKind<'a, O> {
             PathNotFound(ref v) => PathNotFound(v.clone()),
             UnimplementedTraitSelection => UnimplementedTraitSelection,
             TypeckError => TypeckError,
-            ReferencedConstant => ReferencedConstant,
+            ReferencedConstant(ref err) => ReferencedConstant(tcx.lift(err)?),
             OverflowNeg => OverflowNeg,
             Overflow(op) => Overflow(op),
             DivisionByZero => DivisionByZero,
@@ -595,14 +594,7 @@ impl<'a, 'tcx> Lift<'tcx> for const_val::ErrKind<'a> {
         use middle::const_val::ErrKind::*;
 
         Some(match *self {
-            NonConstPath => NonConstPath,
-            UnimplementedConstVal(s) => UnimplementedConstVal(s),
-            IndexOutOfBounds { len, index } => IndexOutOfBounds { len, index },
-
-            LayoutError(ref e) => {
-                return tcx.lift(e).map(LayoutError)
-            }
-
+            CouldNotResolve => CouldNotResolve,
             TypeckError => TypeckError,
             CheckMatchError => CheckMatchError,
             Miri(ref e, ref frames) => return tcx.lift(e).map(|e| Miri(e, frames.clone())),
diff --git a/src/librustc_codegen_llvm/mir/constant.rs b/src/librustc_codegen_llvm/mir/constant.rs
index ef0bc3ed330..7c1035e2fcb 100644
--- a/src/librustc_codegen_llvm/mir/constant.rs
+++ b/src/librustc_codegen_llvm/mir/constant.rs
@@ -217,7 +217,10 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
                 Ok((llval, constant.ty))
             })
             .unwrap_or_else(|e| {
-                e.report(bx.tcx(), constant.span, "shuffle_indices");
+                e.report_as_error(
+                    bx.tcx().at(constant.span),
+                    "could not evaluate shuffle_indices at compile time",
+                );
                 // We've errored, so we don't have to produce working code.
                 let ty = self.monomorphize(&constant.ty);
                 let llty = bx.cx.layout_of(ty).llvm_type(bx.cx);
diff --git a/src/librustc_codegen_llvm/mir/operand.rs b/src/librustc_codegen_llvm/mir/operand.rs
index 98383e882c4..9f32b41cb13 100644
--- a/src/librustc_codegen_llvm/mir/operand.rs
+++ b/src/librustc_codegen_llvm/mir/operand.rs
@@ -416,7 +416,10 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
                                 // FIXME: generate a panic here
                             },
                             mir::Literal::Value { .. } => {
-                                err.report(bx.tcx(), constant.span, "const operand");
+                                err.report_as_error(
+                                    bx.tcx().at(constant.span),
+                                    "could not evaluate constant operand",
+                                );
                             },
                         }
                         // We've errored, so we don't have to produce working code.
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 79c7a791147..d788e312d15 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -1501,24 +1501,11 @@ fn check_const(cx: &LateContext, body_id: hir::BodyId, what: &str) {
     };
     if let Err(err) = cx.tcx.const_eval(param_env.and(cid)) {
         let span = cx.tcx.def_span(def_id);
-        let mut diag = cx.struct_span_lint(
-            CONST_ERR,
-            span,
+        err.report_as_lint(
+            cx.tcx.at(span),
             &format!("this {} cannot be used", what),
+            cx.current_lint_root(),
         );
-        use rustc::middle::const_val::ConstEvalErrDescription;
-        match err.description() {
-            ConstEvalErrDescription::Simple(message) => {
-                diag.span_label(span, message);
-            }
-            ConstEvalErrDescription::Backtrace(miri, frames) => {
-                diag.span_label(span, format!("{}", miri));
-                for frame in frames {
-                    diag.span_label(frame.span, format!("inside call to `{}`", frame.location));
-                }
-            }
-        }
-        diag.emit()
     }
 }
 
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index f6f98f0732e..f23e10ae5d2 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -523,7 +523,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
             let count = match cx.tcx.at(span).const_eval(cx.param_env.and(global_id)) {
                 Ok(cv) => cv.unwrap_usize(cx.tcx),
                 Err(e) => {
-                    e.report(cx.tcx, cx.tcx.def_span(def_id), "array length");
+                    e.report_as_error(cx.tcx.at(span), "could not evaluate array length");
                     0
                 },
             };
diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs
index 0a113970098..7cef8a75aa6 100644
--- a/src/librustc_mir/hair/pattern/check_match.rs
+++ b/src/librustc_mir/hair/pattern/check_match.rs
@@ -141,13 +141,13 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
                 PatternError::FloatBug => {
                     // FIXME(#31407) this is only necessary because float parsing is buggy
                     ::rustc::middle::const_val::struct_error(
-                        self.tcx, pat_span,
+                        self.tcx.at(pat_span),
                         "could not evaluate float literal (see issue #31407)",
                     ).emit();
                 }
                 PatternError::NonConstPath(span) => {
                     ::rustc::middle::const_val::struct_error(
-                        self.tcx, span,
+                        self.tcx.at(span),
                         "runtime values cannot be referenced in patterns",
                     ).emit();
                 }
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs
index 4cfe74413df..7dae79530c4 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir/hair/pattern/mod.rs
@@ -695,7 +695,10 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> {
                                 return self.const_to_pat(instance, value, id, span)
                             },
                             Err(err) => {
-                                err.report(self.tcx, span, "pattern");
+                                err.report_as_error(
+                                    self.tcx.at(span),
+                                    "could not evaluate constant pattern",
+                                );
                                 PatternKind::Wild
                             },
                         }
diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs
index 44832df8240..3fcf1b5c8ed 100644
--- a/src/librustc_mir/interpret/const_eval.rs
+++ b/src/librustc_mir/interpret/const_eval.rs
@@ -65,34 +65,12 @@ pub fn eval_promoted<'a, 'mir, 'tcx>(
     cid: GlobalId<'tcx>,
     mir: &'mir mir::Mir<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
-) -> Option<(Value, Scalar, Ty<'tcx>)> {
+) -> EvalResult<'tcx, (Value, Scalar, Ty<'tcx>)> {
     ecx.with_fresh_body(|ecx| {
-        let res = eval_body_using_ecx(ecx, cid, Some(mir), param_env);
-        match res {
-            Ok(val) => Some(val),
-            Err(mut err) => {
-                ecx.report(&mut err, false, None);
-                None
-            }
-        }
+        eval_body_using_ecx(ecx, cid, Some(mir), param_env)
     })
 }
 
-pub fn eval_body<'a, 'tcx>(
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
-    cid: GlobalId<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-) -> Option<(Value, Scalar, Ty<'tcx>)> {
-    let (res, ecx) = eval_body_and_ecx(tcx, cid, None, param_env);
-    match res {
-        Ok(val) => Some(val),
-        Err(mut err) => {
-            ecx.report(&mut err, true, None);
-            None
-        }
-    }
-}
-
 pub fn value_to_const_value<'tcx>(
     ecx: &EvalContext<'_, '_, 'tcx, CompileTimeEvaluator>,
     val: Value,
@@ -124,9 +102,17 @@ pub fn value_to_const_value<'tcx>(
     })();
     match val {
         Ok(val) => ty::Const::from_const_value(ecx.tcx.tcx, val, ty),
-        Err(mut err) => {
-            ecx.report(&mut err, true, None);
-            bug!("miri error occured when converting Value to ConstValue")
+        Err(err) => {
+            let (frames, span) = ecx.generate_stacktrace(None);
+            let err = ConstEvalErr {
+                span,
+                kind: ErrKind::Miri(err, frames).into(),
+            };
+            err.report_as_error(
+                ecx.tcx,
+                "failed to convert Value to ConstValue, this is a bug",
+            );
+            span_bug!(span, "miri error occured when converting Value to ConstValue")
         }
     }
 }
@@ -578,16 +564,17 @@ pub fn const_eval_provider<'a, 'tcx>(
             val = ecx.try_read_by_ref(val, miri_ty)?;
         }
         Ok(value_to_const_value(&ecx, val, miri_ty))
-    }).map_err(|mut err| {
-        if tcx.is_static(def_id).is_some() {
-            ecx.report(&mut err, true, None);
-        }
+    }).map_err(|err| {
         let (trace, span) = ecx.generate_stacktrace(None);
         let err = ErrKind::Miri(err, trace);
-        ConstEvalErr {
+        let err = ConstEvalErr {
             kind: err.into(),
             span,
+        };
+        if tcx.is_static(def_id).is_some() {
+            err.report_as_error(ecx.tcx, "could not evaluate static initializer");
         }
+        err
     })
 }
 
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 632f7abfdb4..3e91fa72cae 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -3,7 +3,7 @@ use std::fmt::Write;
 use rustc::hir::def_id::DefId;
 use rustc::hir::def::Def;
 use rustc::hir::map::definitions::DefPathData;
-use rustc::middle::const_val::{ConstVal, ErrKind};
+use rustc::middle::const_val::ConstVal;
 use rustc::mir;
 use rustc::ty::layout::{self, Size, Align, HasDataLayout, IntegerExt, LayoutOf, TyLayout};
 use rustc::ty::subst::{Subst, Substs};
@@ -15,7 +15,7 @@ use syntax::codemap::{self, Span};
 use syntax::ast::Mutability;
 use rustc::mir::interpret::{
     GlobalId, Value, Scalar,
-    EvalError, EvalResult, EvalErrorKind, Pointer, ConstValue,
+    EvalResult, EvalErrorKind, Pointer, ConstValue,
 };
 use std::mem;
 
@@ -1056,15 +1056,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
         } else {
             self.param_env
         };
-        self.tcx.const_eval(param_env.and(gid)).map_err(|err| match *err.kind {
-            ErrKind::Miri(ref err, _) => match err.kind {
-                EvalErrorKind::TypeckError |
-                EvalErrorKind::Layout(_) => EvalErrorKind::TypeckError.into(),
-                _ => EvalErrorKind::ReferencedConstant.into(),
-            },
-            ErrKind::TypeckError => EvalErrorKind::TypeckError.into(),
-            ref other => bug!("const eval returned {:?}", other),
-        })
+        self.tcx.const_eval(param_env.and(gid)).map_err(|err| EvalErrorKind::ReferencedConstant(err).into())
     }
 
     pub fn force_allocation(&mut self, place: Place) -> EvalResult<'tcx, Place> {
@@ -1626,7 +1618,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
         let mut last_span = None;
         let mut frames = Vec::new();
         // skip 1 because the last frame is just the environment of the constant
-        for &Frame { instance, span, .. } in self.stack().iter().skip(1).rev() {
+        for &Frame { instance, span, mir, block, stmt, .. } in self.stack().iter().skip(1).rev() {
             // make sure we don't emit frames that are duplicates of the previous
             if explicit_span == Some(span) {
                 last_span = Some(span);
@@ -1644,82 +1636,20 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
             } else {
                 instance.to_string()
             };
-            frames.push(FrameInfo { span, location });
-        }
-        trace!("generate stacktrace: {:#?}, {:?}", frames, explicit_span);
-        (frames, self.tcx.span)
-    }
-
-    pub fn report(&self, e: &mut EvalError, as_err: bool, explicit_span: Option<Span>) {
-        match e.kind {
-            EvalErrorKind::Layout(_) |
-            EvalErrorKind::TypeckError => return,
-            _ => {},
-        }
-        if let Some(ref mut backtrace) = e.backtrace {
-            let mut trace_text = "\n\nAn error occurred in miri:\n".to_string();
-            backtrace.resolve();
-            write!(trace_text, "backtrace frames: {}\n", backtrace.frames().len()).unwrap();
-            'frames: for (i, frame) in backtrace.frames().iter().enumerate() {
-                if frame.symbols().is_empty() {
-                    write!(trace_text, "{}: no symbols\n", i).unwrap();
-                }
-                for symbol in frame.symbols() {
-                    write!(trace_text, "{}: ", i).unwrap();
-                    if let Some(name) = symbol.name() {
-                        write!(trace_text, "{}\n", name).unwrap();
-                    } else {
-                        write!(trace_text, "<unknown>\n").unwrap();
-                    }
-                    write!(trace_text, "\tat ").unwrap();
-                    if let Some(file_path) = symbol.filename() {
-                        write!(trace_text, "{}", file_path.display()).unwrap();
-                    } else {
-                        write!(trace_text, "<unknown_file>").unwrap();
-                    }
-                    if let Some(line) = symbol.lineno() {
-                        write!(trace_text, ":{}\n", line).unwrap();
-                    } else {
-                        write!(trace_text, "\n").unwrap();
-                    }
-                }
-            }
-            error!("{}", trace_text);
-        }
-        if let Some(frame) = self.stack().last() {
-            let block = &frame.mir.basic_blocks()[frame.block];
-            let span = explicit_span.unwrap_or_else(|| if frame.stmt < block.statements.len() {
-                block.statements[frame.stmt].source_info.span
-            } else {
-                block.terminator().source_info.span
-            });
-            trace!("reporting const eval failure at {:?}", span);
-            let mut err = if as_err {
-                ::rustc::middle::const_val::struct_error(*self.tcx, span, "constant evaluation error")
+            let block = &mir.basic_blocks()[block];
+            let source_info = if stmt < block.statements.len() {
+                block.statements[stmt].source_info
             } else {
-                let node_id = self
-                    .stack()
-                    .iter()
-                    .rev()
-                    .filter_map(|frame| self.tcx.hir.as_local_node_id(frame.instance.def_id()))
-                    .next()
-                    .expect("some part of a failing const eval must be local");
-                self.tcx.struct_span_lint_node(
-                    ::rustc::lint::builtin::CONST_ERR,
-                    node_id,
-                    span,
-                    "constant evaluation error",
-                )
+                block.terminator().source_info
             };
-            let (frames, span) = self.generate_stacktrace(explicit_span);
-            err.span_label(span, e.to_string());
-            for FrameInfo { span, location } in frames {
-                err.span_note(span, &format!("inside call to `{}`", location));
-            }
-            err.emit();
-        } else {
-            self.tcx.sess.err(&e.to_string());
+            let lint_root = match mir.source_scope_local_data {
+                mir::ClearCrossCrate::Set(ref ivs) => Some(ivs[source_info.scope].lint_root),
+                mir::ClearCrossCrate::Clear => None,
+            };
+            frames.push(FrameInfo { span, location, lint_root });
         }
+        trace!("generate stacktrace: {:#?}, {:?}", frames, explicit_span);
+        (frames, self.tcx.span)
     }
 
     pub fn sign_extend(&self, value: u128, ty: Ty<'tcx>) -> EvalResult<'tcx, u128> {
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index dc56de47fbf..ec308c2193d 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -7,7 +7,7 @@ use rustc::ty::ParamEnv;
 use rustc::ty::maps::TyCtxtAt;
 use rustc::ty::layout::{self, Align, TargetDataLayout, Size};
 use syntax::ast::Mutability;
-use rustc::middle::const_val::{ConstVal, ErrKind};
+use rustc::middle::const_val::ConstVal;
 
 use rustc_data_structures::fx::{FxHashSet, FxHashMap};
 use rustc::mir::interpret::{Pointer, AllocId, Allocation, AccessKind, Value,
@@ -285,16 +285,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
             instance,
             promoted: None,
         };
-        self.tcx.const_eval(ParamEnv::reveal_all().and(gid)).map_err(|err| {
-            match *err.kind {
-                ErrKind::Miri(ref err, _) => match err.kind {
-                    EvalErrorKind::TypeckError |
-                    EvalErrorKind::Layout(_) => EvalErrorKind::TypeckError.into(),
-                    _ => EvalErrorKind::ReferencedConstant.into(),
-                },
-                ErrKind::TypeckError => EvalErrorKind::TypeckError.into(),
-                ref other => bug!("const eval returned {:?}", other),
-            }
+        self.tcx.const_eval(ParamEnv::reveal_all().and(gid)).map_err(|_| {
+            // no need to report anything, the const_eval call takes care of that for statics
+            assert!(self.tcx.is_static(def_id).is_some());
+            EvalErrorKind::TypeckError.into()
         }).map(|val| {
             let const_val = match val.val {
                 ConstVal::Value(val) => val,
diff --git a/src/librustc_mir/interpret/mod.rs b/src/librustc_mir/interpret/mod.rs
index b5b4ac6df6b..3afcd6f2d9b 100644
--- a/src/librustc_mir/interpret/mod.rs
+++ b/src/librustc_mir/interpret/mod.rs
@@ -21,7 +21,6 @@ pub use self::memory::{Memory, MemoryKind, HasMemory};
 pub use self::const_eval::{
     eval_promoted,
     mk_borrowck_eval_cx,
-    eval_body,
     CompileTimeEvaluator,
     const_value_to_allocation_provider,
     const_eval_provider,
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index a8a50e14c68..a8a50c50f59 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -388,7 +388,10 @@ fn collect_items_rec<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 Ok(val) => collect_const(tcx, val, instance.substs, &mut neighbors),
                 Err(err) => {
                     let span = tcx.def_span(def_id);
-                    err.report(tcx, span, "static");
+                    err.report_as_error(
+                        tcx.at(span),
+                        "could not evaluate static initializer",
+                    );
                 }
             }
         }
@@ -1187,13 +1190,25 @@ fn collect_neighbours<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     let param_env = ty::ParamEnv::reveal_all();
     for i in 0..mir.promoted.len() {
         use rustc_data_structures::indexed_vec::Idx;
+        let i = Promoted::new(i);
         let cid = GlobalId {
             instance,
-            promoted: Some(Promoted::new(i)),
+            promoted: Some(i),
         };
         match tcx.const_eval(param_env.and(cid)) {
             Ok(val) => collect_const(tcx, val, instance.substs, output),
-            Err(_) => {},
+            Err(err) => {
+                use rustc::middle::const_val::ErrKind;
+                use rustc::mir::interpret::EvalErrorKind;
+                if let ErrKind::Miri(ref miri, ..) = *err.kind {
+                    if let EvalErrorKind::ReferencedConstant(_) = miri.kind {
+                        err.report_as_error(
+                            tcx.at(mir.promoted[i].span),
+                            "erroneous constant used",
+                        );
+                    }
+                }
+            },
         }
     }
 }
@@ -1236,7 +1251,10 @@ fn collect_const<'a, 'tcx>(
                 Ok(val) => val.val,
                 Err(err) => {
                     let span = tcx.def_span(def_id);
-                    err.report(tcx, span, "constant");
+                    err.report_as_error(
+                        tcx.at(span),
+                        "constant evaluation error",
+                    );
                     return;
                 }
             }
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index d39042ceba9..24382815084 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -17,7 +17,7 @@ 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, ProjectionElem};
 use rustc::mir::visit::{Visitor, PlaceContext};
-use rustc::middle::const_val::ConstVal;
+use rustc::middle::const_val::{ConstVal, ConstEvalErr, ErrKind};
 use rustc::ty::{TyCtxt, self, Instance};
 use rustc::mir::interpret::{Value, Scalar, GlobalId, EvalResult};
 use interpret::EvalContext;
@@ -121,17 +121,37 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
 
     fn use_ecx<F, T>(
         &mut self,
-        span: Span,
+        source_info: SourceInfo,
         f: F
     ) -> Option<T>
     where
         F: FnOnce(&mut Self) -> EvalResult<'tcx, T>,
     {
-        self.ecx.tcx.span = span;
+        self.ecx.tcx.span = source_info.span;
+        let lint_root = match self.mir.source_scope_local_data {
+            ClearCrossCrate::Set(ref ivs) => {
+                use rustc_data_structures::indexed_vec::Idx;
+                //FIXME(#51314): remove this check
+                if source_info.scope.index() >= ivs.len() {
+                    return None;
+                }
+                ivs[source_info.scope].lint_root
+            },
+            ClearCrossCrate::Clear => return None,
+        };
         let r = match f(self) {
             Ok(val) => Some(val),
-            Err(mut err) => {
-                self.ecx.report(&mut err, false, Some(span));
+            Err(err) => {
+                let (frames, span) = self.ecx.generate_stacktrace(None);
+                let err = ConstEvalErr {
+                    span,
+                    kind: ErrKind::Miri(err, frames).into(),
+                };
+                err.report_as_lint(
+                    self.ecx.tcx,
+                    "this expression will panic at runtime",
+                    lint_root,
+                );
                 None
             },
         };
@@ -139,30 +159,37 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
         r
     }
 
-    fn const_eval(&mut self, cid: GlobalId<'tcx>, span: Span) -> Option<Const<'tcx>> {
+    fn const_eval(&mut self, cid: GlobalId<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
         let value = match self.tcx.const_eval(self.param_env.and(cid)) {
             Ok(val) => val,
             Err(err) => {
-                err.report(self.tcx, err.span, "constant propagated");
+                err.report_as_error(
+                    self.tcx.at(err.span),
+                    "constant evaluation error",
+                );
                 return None;
             },
         };
         let val = match value.val {
             ConstVal::Value(v) => {
-                self.use_ecx(span, |this| this.ecx.const_value_to_value(v, value.ty))?
+                self.use_ecx(source_info, |this| this.ecx.const_value_to_value(v, value.ty))?
             },
             _ => bug!("eval produced: {:?}", value),
         };
-        let val = (val, value.ty, span);
+        let val = (val, value.ty, source_info.span);
         trace!("evaluated {:?} to {:?}", cid, val);
         Some(val)
     }
 
-    fn eval_constant(&mut self, c: &Constant<'tcx>) -> Option<Const<'tcx>> {
+    fn eval_constant(
+        &mut self,
+        c: &Constant<'tcx>,
+        source_info: SourceInfo,
+    ) -> Option<Const<'tcx>> {
         match c.literal {
             Literal::Value { value } => match value.val {
                 ConstVal::Value(v) => {
-                    let v = self.use_ecx(c.span, |this| {
+                    let v = self.use_ecx(source_info, |this| {
                         this.ecx.const_value_to_value(v, value.ty)
                     })?;
                     Some((v, value.ty, c.span))
@@ -178,7 +205,7 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
                         instance,
                         promoted: None,
                     };
-                    self.const_eval(cid, c.span)
+                    self.const_eval(cid, source_info)
                 },
             },
             // evaluate the promoted and replace the constant with the evaluated result
@@ -196,10 +223,9 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
                 };
                 // cannot use `const_eval` here, because that would require having the MIR
                 // for the current function available, but we're producing said MIR right now
-                let span = self.mir.span;
-                let (value, _, ty) = self.use_ecx(span, |this| {
-                    Ok(eval_promoted(&mut this.ecx, cid, this.mir, this.param_env))
-                })??;
+                let (value, _, ty) = self.use_ecx(source_info, |this| {
+                    eval_promoted(&mut this.ecx, cid, this.mir, this.param_env)
+                })?;
                 let val = (value, ty, c.span);
                 trace!("evaluated {:?} to {:?}", c, val);
                 Some(val)
@@ -207,14 +233,14 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
         }
     }
 
-    fn eval_place(&mut self, place: &Place<'tcx>) -> Option<Const<'tcx>> {
+    fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> 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)?;
-                    let valty = self.use_ecx(span, |this| {
+                    let (base, ty, span) = self.eval_place(&proj.base, source_info)?;
+                    let valty = self.use_ecx(source_info, |this| {
                         this.ecx.read_field(base, None, field, ty)
                     })?;
                     Some((valty.value, valty.ty, span))
@@ -225,10 +251,11 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
         }
     }
 
-    fn eval_operand(&mut self, op: &Operand<'tcx>) -> Option<Const<'tcx>> {
+    fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
         match *op {
-            Operand::Constant(ref c) => self.eval_constant(c),
-            Operand::Move(ref place) | Operand::Copy(ref place) => self.eval_place(place),
+            Operand::Constant(ref c) => self.eval_constant(c, source_info),
+            | Operand::Move(ref place)
+            | Operand::Copy(ref place) => self.eval_place(place, source_info),
         }
     }
 
@@ -243,10 +270,10 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
             // This branch exists for the sanity type check
             Rvalue::Use(Operand::Constant(ref c)) => {
                 assert_eq!(c.ty, place_ty);
-                self.eval_constant(c)
+                self.eval_constant(c, source_info)
             },
             Rvalue::Use(ref op) => {
-                self.eval_operand(op)
+                self.eval_operand(op, source_info)
             },
             Rvalue::Repeat(..) |
             Rvalue::Ref(..) |
@@ -279,17 +306,17 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
                     return None;
                 }
 
-                let val = self.eval_operand(arg)?;
-                let prim = self.use_ecx(span, |this| {
+                let val = self.eval_operand(arg, source_info)?;
+                let prim = self.use_ecx(source_info, |this| {
                     this.ecx.value_to_scalar(ValTy { value: val.0, ty: val.1 })
                 })?;
-                let val = self.use_ecx(span, |this| this.ecx.unary_op(op, prim, val.1))?;
+                let val = self.use_ecx(source_info, |this| this.ecx.unary_op(op, prim, val.1))?;
                 Some((Value::Scalar(val), place_ty, span))
             }
             Rvalue::CheckedBinaryOp(op, ref left, ref right) |
             Rvalue::BinaryOp(op, ref left, ref right) => {
                 trace!("rvalue binop {:?} for {:?} and {:?}", op, left, right);
-                let right = self.eval_operand(right)?;
+                let right = self.eval_operand(right, source_info)?;
                 let def_id = if self.tcx.is_closure(self.source.def_id) {
                     self.tcx.closure_base_def_id(self.source.def_id)
                 } else {
@@ -301,7 +328,7 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
                     return None;
                 }
 
-                let r = self.use_ecx(span, |this| {
+                let r = self.use_ecx(source_info, |this| {
                     this.ecx.value_to_scalar(ValTy { value: right.0, ty: right.1 })
                 })?;
                 if op == BinOp::Shr || op == BinOp::Shl {
@@ -332,12 +359,12 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
                         return None;
                     }
                 }
-                let left = self.eval_operand(left)?;
-                let l = self.use_ecx(span, |this| {
+                let left = self.eval_operand(left, source_info)?;
+                let l = self.use_ecx(source_info, |this| {
                     this.ecx.value_to_scalar(ValTy { value: left.0, ty: left.1 })
                 })?;
                 trace!("const evaluating {:?} for {:?} and {:?}", op, left, right);
-                let (val, overflow) = self.use_ecx(span, |this| {
+                let (val, overflow) = self.use_ecx(source_info, |this| {
                     this.ecx.binary_op(op, l, left.1, r, right.1)
                 })?;
                 let val = if let Rvalue::CheckedBinaryOp(..) = *rvalue {
@@ -348,11 +375,8 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
                 } else {
                     if overflow {
                         use rustc::mir::interpret::EvalErrorKind;
-                        let mut err = EvalErrorKind::Overflow(op).into();
-                        self.use_ecx(span, |this| {
-                            this.ecx.report(&mut err, false, Some(span));
-                            Ok(())
-                        });
+                        let err = EvalErrorKind::Overflow(op).into();
+                        let _: Option<()> = self.use_ecx(source_info, |_| Err(err));
                         return None;
                     }
                     Value::Scalar(val)
@@ -431,7 +455,8 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
     ) {
         trace!("visit_constant: {:?}", constant);
         self.super_constant(constant, location);
-        self.eval_constant(constant);
+        let source_info = *self.mir.source_info(location);
+        self.eval_constant(constant, source_info);
     }
 
     fn visit_statement(
@@ -466,8 +491,9 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
         location: Location,
     ) {
         self.super_terminator_kind(block, kind, location);
+        let source_info = *self.mir.source_info(location);
         if let TerminatorKind::Assert { expected, msg, cond, .. } = kind {
-            if let Some(value) = self.eval_operand(cond) {
+            if let Some(value) = self.eval_operand(cond, source_info) {
                 trace!("assertion on {:?} should be {:?}", value, expected);
                 if Value::Scalar(Scalar::from_bool(*expected)) != value.0 {
                     // poison all places this operand references so that further code
@@ -502,13 +528,15 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
                         DivisionByZero |
                         RemainderByZero => msg.description().to_owned(),
                         BoundsCheck { ref len, ref index } => {
-                            let len = self.eval_operand(len).expect("len must be const");
+                            let len = self
+                                .eval_operand(len, source_info)
+                                .expect("len must be const");
                             let len = match len.0 {
                                 Value::Scalar(Scalar::Bits { bits, ..}) => bits,
                                 _ => bug!("const len not primitive: {:?}", len),
                             };
                             let index = self
-                                .eval_operand(index)
+                                .eval_operand(index, source_info)
                                 .expect("index must be const");
                             let index = match index.0 {
                                 Value::Scalar(Scalar::Bits { bits, .. }) => bits,
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index c2c71d90f06..83a654aaae9 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -4040,7 +4040,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             let count = tcx.const_eval(param_env.and(global_id));
 
             if let Err(ref err) = count {
-                err.report(tcx, tcx.def_span(count_def_id), "constant expression");
+                err.report_as_error(
+                    tcx.at(tcx.def_span(count_def_id)),
+                    "could not evaluate repeat length",
+                );
             }
 
             let uty = match expected {
diff --git a/src/test/compile-fail/const-array-oob.rs b/src/test/compile-fail/const-array-oob.rs
index 108b7948dfc..22a3c5ceeb7 100644
--- a/src/test/compile-fail/const-array-oob.rs
+++ b/src/test/compile-fail/const-array-oob.rs
@@ -16,7 +16,7 @@ const FOO: [usize; 3] = [1, 2, 3];
 const BAR: usize = FOO[5]; // no error, because the error below occurs before regular const eval
 
 const BLUB: [u32; FOO[4]] = [5, 6];
-//~^ ERROR constant evaluation error [E0080]
+//~^ ERROR could not evaluate constant expression [E0080]
 //~| index out of bounds: the len is 3 but the index is 4
 
 fn main() {
diff --git a/src/test/compile-fail/const-err-early.rs b/src/test/compile-fail/const-err-early.rs
index f8b20f6ee79..92c6b1fd0b5 100644
--- a/src/test/compile-fail/const-err-early.rs
+++ b/src/test/compile-fail/const-err-early.rs
@@ -12,7 +12,7 @@
 
 pub const A: i8 = -std::i8::MIN; //~ ERROR const_err
 //~^ ERROR this constant cannot be used
-//~| ERROR constant evaluation error
+//~| ERROR this expression will panic at runtime
 pub const B: u8 = 200u8 + 200u8; //~ ERROR const_err
 //~^ ERROR this constant cannot be used
 pub const C: u8 = 200u8 * 4; //~ ERROR const_err
diff --git a/src/test/compile-fail/const-err-multi.rs b/src/test/compile-fail/const-err-multi.rs
index 6f0281b8bd0..4a5e78b381e 100644
--- a/src/test/compile-fail/const-err-multi.rs
+++ b/src/test/compile-fail/const-err-multi.rs
@@ -13,14 +13,17 @@
 pub const A: i8 = -std::i8::MIN;
 //~^ ERROR E0080
 //~| ERROR attempt to negate with overflow
-//~| ERROR constant evaluation error
+//~| ERROR this expression will panic at runtime
 //~| ERROR this constant cannot be used
 pub const B: i8 = A;
 //~^ ERROR const_err
+//~| ERROR const_err
 pub const C: u8 = A as u8;
 //~^ ERROR const_err
+//~| ERROR const_err
 pub const D: i8 = 50 - A;
 //~^ ERROR const_err
+//~| ERROR const_err
 
 fn main() {
     let _ = (A, B, C, D);
diff --git a/src/test/compile-fail/const-err.rs b/src/test/compile-fail/const-err.rs
index f6a64bcba21..f77603b3eba 100644
--- a/src/test/compile-fail/const-err.rs
+++ b/src/test/compile-fail/const-err.rs
@@ -23,6 +23,7 @@ fn black_box<T>(_: T) {
 // Make sure that the two uses get two errors.
 const FOO: u8 = [5u8][1];
 //~^ ERROR constant evaluation error
+//~| ERROR constant evaluation error
 //~| index out of bounds: the len is 1 but the index is 1
 
 fn main() {
diff --git a/src/test/compile-fail/const-integer-bool-ops.rs b/src/test/compile-fail/const-integer-bool-ops.rs
index 3065122af6a..29bc665a22e 100644
--- a/src/test/compile-fail/const-integer-bool-ops.rs
+++ b/src/test/compile-fail/const-integer-bool-ops.rs
@@ -16,7 +16,6 @@ const X: usize = 42 && 39;
 //~| ERROR mismatched types
 //~| expected usize, found bool
 const ARR: [i32; X] = [99; 34];
-//~^ ERROR constant evaluation error
 
 const X1: usize = 42 || 39;
 //~^ ERROR mismatched types
@@ -26,7 +25,6 @@ const X1: usize = 42 || 39;
 //~| ERROR mismatched types
 //~| expected usize, found bool
 const ARR1: [i32; X1] = [99; 47];
-//~^ ERROR constant evaluation error
 
 const X2: usize = -42 || -39;
 //~^ ERROR mismatched types
@@ -36,7 +34,6 @@ const X2: usize = -42 || -39;
 //~| ERROR mismatched types
 //~| expected usize, found bool
 const ARR2: [i32; X2] = [99; 18446744073709551607];
-//~^ ERROR constant evaluation error
 
 const X3: usize = -42 && -39;
 //~^ ERROR mismatched types
@@ -46,43 +43,36 @@ const X3: usize = -42 && -39;
 //~| ERROR mismatched types
 //~| expected usize, found bool
 const ARR3: [i32; X3] = [99; 6];
-//~^ ERROR constant evaluation error
 
 const Y: usize = 42.0 == 42.0;
 //~^ ERROR mismatched types
 //~| expected usize, found bool
 const ARRR: [i32; Y] = [99; 1];
-//~^ ERROR constant evaluation error
 
 const Y1: usize = 42.0 >= 42.0;
 //~^ ERROR mismatched types
 //~| expected usize, found bool
 const ARRR1: [i32; Y1] = [99; 1];
-//~^ ERROR constant evaluation error
 
 const Y2: usize = 42.0 <= 42.0;
 //~^ ERROR mismatched types
 //~| expected usize, found bool
 const ARRR2: [i32; Y2] = [99; 1];
-//~^ ERROR constant evaluation error
 
 const Y3: usize = 42.0 > 42.0;
 //~^ ERROR mismatched types
 //~| expected usize, found bool
 const ARRR3: [i32; Y3] = [99; 0];
-//~^ ERROR constant evaluation error
 
 const Y4: usize = 42.0 < 42.0;
 //~^ ERROR mismatched types
 //~| expected usize, found bool
 const ARRR4: [i32; Y4] = [99; 0];
-//~^ ERROR constant evaluation error
 
 const Y5: usize = 42.0 != 42.0;
 //~^ ERROR mismatched types
 //~| expected usize, found bool
 const ARRR5: [i32; Y5] = [99; 0];
-//~^ ERROR constant evaluation error
 
 fn main() {
     let _ = ARR;
diff --git a/src/test/compile-fail/const-len-underflow-subspans.rs b/src/test/compile-fail/const-len-underflow-subspans.rs
index 85cc893aa13..054c272a3d3 100644
--- a/src/test/compile-fail/const-len-underflow-subspans.rs
+++ b/src/test/compile-fail/const-len-underflow-subspans.rs
@@ -16,6 +16,6 @@ const TWO: usize = 2;
 
 fn main() {
     let a: [i8; ONE - TWO] = unimplemented!();
-    //~^ ERROR constant evaluation error
+    //~^ ERROR could not evaluate constant expression
     //~| attempt to subtract with overflow
 }
diff --git a/src/test/compile-fail/const-match-check.rs b/src/test/compile-fail/const-match-check.rs
index 36a6600b62d..304eef7847c 100644
--- a/src/test/compile-fail/const-match-check.rs
+++ b/src/test/compile-fail/const-match-check.rs
@@ -40,5 +40,4 @@ fn main() {
     #[cfg(eval2)]
     let x: [i32; { let 0 = 0; 0 }] = [];
     //[eval2]~^ ERROR refutable pattern in local binding
-    //[eval2]~| ERROR constant evaluation error
 }
diff --git a/src/test/compile-fail/const-tup-index-span.rs b/src/test/compile-fail/const-tup-index-span.rs
index 7596881ef9b..b42c440f87d 100644
--- a/src/test/compile-fail/const-tup-index-span.rs
+++ b/src/test/compile-fail/const-tup-index-span.rs
@@ -14,7 +14,6 @@ const TUP: (usize,) = 5usize << 64;
 //~^ ERROR mismatched types
 //~| expected tuple, found usize
 const ARR: [i32; TUP.0] = [];
-//~^ ERROR constant evaluation error
 
 fn main() {
 }
diff --git a/src/test/compile-fail/eval-enum.rs b/src/test/compile-fail/eval-enum.rs
index 73156168602..ada038114d8 100644
--- a/src/test/compile-fail/eval-enum.rs
+++ b/src/test/compile-fail/eval-enum.rs
@@ -11,12 +11,12 @@
 enum Test {
     DivZero = 1/0,
     //~^ attempt to divide by zero
-    //~| ERROR constant evaluation error
-    //~| ERROR constant evaluation error
+    //~| ERROR could not evaluate enum discriminant
+    //~| ERROR this expression will panic at runtime
     RemZero = 1%0,
     //~^ attempt to calculate the remainder with a divisor of zero
-    //~| ERROR constant evaluation error
-    //~| ERROR constant evaluation error
+    //~| ERROR could not evaluate enum discriminant
+    //~| ERROR this expression will panic at runtime
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/issue-43105.rs b/src/test/compile-fail/issue-43105.rs
index 6fa65a541b3..8a0471135af 100644
--- a/src/test/compile-fail/issue-43105.rs
+++ b/src/test/compile-fail/issue-43105.rs
@@ -12,11 +12,11 @@ fn xyz() -> u8 { 42 }
 
 const NUM: u8 = xyz();
 //~^ ERROR calls in constants are limited to constant functions, tuple structs and tuple variants
-//~| ERROR constant evaluation error
 
 fn main() {
     match 1 {
         NUM => unimplemented!(),
+        //~^ ERROR could not evaluate constant pattern
         _ => unimplemented!(),
     }
 }
diff --git a/src/test/compile-fail/issue-8460-const.rs b/src/test/compile-fail/issue-8460-const.rs
index 1d59e75a0f0..b0d6cb5df87 100644
--- a/src/test/compile-fail/issue-8460-const.rs
+++ b/src/test/compile-fail/issue-8460-const.rs
@@ -16,62 +16,62 @@ use std::thread;
 fn main() {
     assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err());
     //~^ ERROR attempt to divide with overflow
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err());
     //~^ ERROR attempt to divide with overflow
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err());
     //~^ ERROR attempt to divide with overflow
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err());
     //~^ ERROR attempt to divide with overflow
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err());
     //~^ ERROR attempt to divide with overflow
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err());
     //~^ ERROR attempt to divide by zero
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err());
     //~^ ERROR attempt to divide by zero
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err());
     //~^ ERROR attempt to divide by zero
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err());
     //~^ ERROR attempt to divide by zero
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err());
     //~^ ERROR attempt to divide by zero
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
     //~^ ERROR attempt to calculate the remainder with overflow
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
     //~^ ERROR attempt to calculate the remainder with overflow
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
     //~^ ERROR attempt to calculate the remainder with overflow
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
     //~^ ERROR attempt to calculate the remainder with overflow
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
     //~^ ERROR attempt to calculate the remainder with overflow
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err());
     //~^ ERROR attempt to calculate the remainder with a divisor of zero
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err());
     //~^ ERROR attempt to calculate the remainder with a divisor of zero
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err());
     //~^ ERROR attempt to calculate the remainder with a divisor of zero
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err());
     //~^ ERROR attempt to calculate the remainder with a divisor of zero
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
     assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err());
     //~^ ERROR attempt to calculate the remainder with a divisor of zero
-    //~| ERROR constant evaluation error
+    //~| ERROR this expression will panic at runtime
 }
diff --git a/src/test/ui/const-eval-overflow-2.rs b/src/test/ui/const-eval-overflow-2.rs
index 63f33cafaf8..ce3d54ee46d 100644
--- a/src/test/ui/const-eval-overflow-2.rs
+++ b/src/test/ui/const-eval-overflow-2.rs
@@ -19,11 +19,11 @@ use std::{u8, u16, u32, u64, usize};
 
 const NEG_128: i8 = -128;
 const NEG_NEG_128: i8 = -NEG_128;
-//~^ ERROR E0080
 
 fn main() {
     match -128i8 {
         NEG_NEG_128 => println!("A"),
+        //~^ ERROR could not evaluate constant pattern
         _ => println!("B"),
     }
 }
diff --git a/src/test/ui/const-eval-overflow-2.stderr b/src/test/ui/const-eval-overflow-2.stderr
index 9cee718c286..e99d409880e 100644
--- a/src/test/ui/const-eval-overflow-2.stderr
+++ b/src/test/ui/const-eval-overflow-2.stderr
@@ -1,12 +1,9 @@
-error[E0080]: constant evaluation error
-  --> $DIR/const-eval-overflow-2.rs:21:25
+error[E0080]: could not evaluate constant pattern
+  --> $DIR/const-eval-overflow-2.rs:25:9
    |
 LL | const NEG_NEG_128: i8 = -NEG_128;
-   |                         ^^^^^^^^ attempt to negate with overflow
-   |
-note: for pattern here
-  --> $DIR/const-eval-overflow-2.rs:26:9
-   |
+   |                         -------- attempt to negate with overflow
+...
 LL |         NEG_NEG_128 => println!("A"),
    |         ^^^^^^^^^^^
 
diff --git a/src/test/ui/const-eval-overflow-4.rs b/src/test/ui/const-eval-overflow-4.rs
index ed14036b0b4..9fc31b7c727 100644
--- a/src/test/ui/const-eval-overflow-4.rs
+++ b/src/test/ui/const-eval-overflow-4.rs
@@ -20,9 +20,9 @@ use std::{i8, i16, i32, i64, isize};
 use std::{u8, u16, u32, u64, usize};
 
 const A_I8_T
+    //~^ ERROR could not evaluate constant expression
     : [u32; (i8::MAX as i8 + 1i8) as usize]
-    //~^ ERROR E0080
-    //~| ERROR attempt to add with overflow
+    //~^ ERROR 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 fc4762f0554..058c8730d7c 100644
--- a/src/test/ui/const-eval-overflow-4.stderr
+++ b/src/test/ui/const-eval-overflow-4.stderr
@@ -1,16 +1,21 @@
 error: attempt to add with overflow
-  --> $DIR/const-eval-overflow-4.rs:23:13
+  --> $DIR/const-eval-overflow-4.rs:24:13
    |
 LL |     : [u32; (i8::MAX as i8 + 1i8) as usize]
    |             ^^^^^^^^^^^^^^^^^^^^^
    |
    = note: #[deny(const_err)] on by default
 
-error[E0080]: constant evaluation error
-  --> $DIR/const-eval-overflow-4.rs:23:13
+error[E0080]: could not evaluate constant expression
+  --> $DIR/const-eval-overflow-4.rs:22:1
    |
-LL |     : [u32; (i8::MAX as i8 + 1i8) as usize]
-   |             ^^^^^^^^^^^^^^^^^^^^^ attempt to add with overflow
+LL | / const A_I8_T
+LL | |     //~^ ERROR could not evaluate constant expression
+LL | |     : [u32; (i8::MAX as i8 + 1i8) as usize]
+   | |             --------------------- attempt to add with overflow
+LL | |     //~^ ERROR attempt to add with overflow
+LL | |     = [0; (i8::MAX as usize) + 1];
+   | |__________________________________^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/const-eval/conditional_array_execution.nll.stderr b/src/test/ui/const-eval/conditional_array_execution.nll.stderr
new file mode 100644
index 00000000000..3580950854d
--- /dev/null
+++ b/src/test/ui/const-eval/conditional_array_execution.nll.stderr
@@ -0,0 +1,74 @@
+warning: attempt to subtract with overflow
+  --> $DIR/conditional_array_execution.rs:15:19
+   |
+LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
+   |                   ^^^^^
+   |
+note: lint level defined here
+  --> $DIR/conditional_array_execution.rs:11:9
+   |
+LL | #![warn(const_err)]
+   |         ^^^^^^^^^
+
+warning: this constant cannot be used
+  --> $DIR/conditional_array_execution.rs:15:1
+   |
+LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
+   | ^^^^^^^^^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                   |
+   |                   attempt to subtract with overflow
+
+warning: referenced constant
+  --> $DIR/conditional_array_execution.rs:20:20
+   |
+LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
+   |                   ----- attempt to subtract with overflow
+...
+LL |     println!("{}", FOO);
+   |                    ^^^
+
+warning: this expression will panic at runtime
+  --> $DIR/conditional_array_execution.rs:20:20
+   |
+LL |     println!("{}", FOO);
+   |                    ^^^ referenced constant has errors
+
+error[E0080]: referenced constant
+  --> $DIR/conditional_array_execution.rs:20:5
+   |
+LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
+   |                   ----- attempt to subtract with overflow
+...
+LL |     println!("{}", FOO);
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error[E0080]: erroneous constant used
+  --> $DIR/conditional_array_execution.rs:20:5
+   |
+LL |     println!("{}", FOO);
+   |     ^^^^^^^^^^^^^^^---^^
+   |                    |
+   |                    referenced constant has errors
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error[E0080]: referenced constant
+  --> $DIR/conditional_array_execution.rs:20:20
+   |
+LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
+   |                   ----- attempt to subtract with overflow
+...
+LL |     println!("{}", FOO);
+   |                    ^^^
+
+error[E0080]: erroneous constant used
+  --> $DIR/conditional_array_execution.rs:20:20
+   |
+LL |     println!("{}", FOO);
+   |                    ^^^ referenced constant has errors
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/const-eval/conditional_array_execution.rs b/src/test/ui/const-eval/conditional_array_execution.rs
index 8952a8386d7..ac555b25afd 100644
--- a/src/test/ui/const-eval/conditional_array_execution.rs
+++ b/src/test/ui/const-eval/conditional_array_execution.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-pass
 #![warn(const_err)]
 
 const X: u32 = 5;
@@ -19,5 +18,8 @@ const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
 
 fn main() {
     println!("{}", FOO);
-    //~^ WARN constant evaluation error
+    //~^ WARN this expression will panic at runtime
+    //~| WARN referenced constant
+    //~| ERROR erroneous constant used
+    //~| E0080
 }
diff --git a/src/test/ui/const-eval/conditional_array_execution.stderr b/src/test/ui/const-eval/conditional_array_execution.stderr
index 5cf73b9fad6..64010c946a7 100644
--- a/src/test/ui/const-eval/conditional_array_execution.stderr
+++ b/src/test/ui/const-eval/conditional_array_execution.stderr
@@ -1,24 +1,53 @@
 warning: attempt to subtract with overflow
-  --> $DIR/conditional_array_execution.rs:16:19
+  --> $DIR/conditional_array_execution.rs:15:19
    |
 LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
    |                   ^^^^^
    |
 note: lint level defined here
-  --> $DIR/conditional_array_execution.rs:12:9
+  --> $DIR/conditional_array_execution.rs:11:9
    |
 LL | #![warn(const_err)]
    |         ^^^^^^^^^
 
 warning: this constant cannot be used
-  --> $DIR/conditional_array_execution.rs:16:1
+  --> $DIR/conditional_array_execution.rs:15:1
    |
 LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
+   | ^^^^^^^^^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                   |
+   |                   attempt to subtract with overflow
 
-warning: constant evaluation error
-  --> $DIR/conditional_array_execution.rs:21:20
+warning: referenced constant
+  --> $DIR/conditional_array_execution.rs:20:20
+   |
+LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
+   |                   ----- attempt to subtract with overflow
+...
+LL |     println!("{}", FOO);
+   |                    ^^^
+
+warning: this expression will panic at runtime
+  --> $DIR/conditional_array_execution.rs:20:20
    |
 LL |     println!("{}", FOO);
    |                    ^^^ referenced constant has errors
 
+error[E0080]: referenced constant
+  --> $DIR/conditional_array_execution.rs:20:20
+   |
+LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
+   |                   ----- attempt to subtract with overflow
+...
+LL |     println!("{}", FOO);
+   |                    ^^^
+
+error[E0080]: erroneous constant used
+  --> $DIR/conditional_array_execution.rs:20:20
+   |
+LL |     println!("{}", FOO);
+   |                    ^^^ referenced constant has errors
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/const-eval/index_out_of_bounds.rs b/src/test/ui/const-eval/index_out_of_bounds.rs
index f3578bcef6e..55c64d2b04e 100644
--- a/src/test/ui/const-eval/index_out_of_bounds.rs
+++ b/src/test/ui/const-eval/index_out_of_bounds.rs
@@ -10,6 +10,7 @@
 
 static FOO: i32 = [][0];
 //~^ ERROR E0080
+//~| ERROR E0080
 
 fn main() {
     let array = [std::env::args().len()];
diff --git a/src/test/ui/const-eval/index_out_of_bounds.stderr b/src/test/ui/const-eval/index_out_of_bounds.stderr
index 96e592dc209..828fba55a3a 100644
--- a/src/test/ui/const-eval/index_out_of_bounds.stderr
+++ b/src/test/ui/const-eval/index_out_of_bounds.stderr
@@ -1,17 +1,25 @@
-error[E0080]: constant evaluation error
+error[E0080]: could not evaluate static initializer
   --> $DIR/index_out_of_bounds.rs:11:19
    |
 LL | static FOO: i32 = [][0];
    |                   ^^^^^ index out of bounds: the len is 0 but the index is 0
 
+error[E0080]: could not evaluate static initializer
+  --> $DIR/index_out_of_bounds.rs:11:1
+   |
+LL | static FOO: i32 = [][0];
+   | ^^^^^^^^^^^^^^^^^^-----^
+   |                   |
+   |                   index out of bounds: the len is 0 but the index is 0
+
 error: index out of bounds: the len is 1 but the index is 1
-  --> $DIR/index_out_of_bounds.rs:16:5
+  --> $DIR/index_out_of_bounds.rs:17:5
    |
 LL |     array[1]; //~ ERROR index out of bounds
    |     ^^^^^^^^
    |
    = note: #[deny(const_err)] on by default
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/const-eval/issue-43197.nll.stderr b/src/test/ui/const-eval/issue-43197.nll.stderr
new file mode 100644
index 00000000000..3bde12ade90
--- /dev/null
+++ b/src/test/ui/const-eval/issue-43197.nll.stderr
@@ -0,0 +1,118 @@
+warning: attempt to subtract with overflow
+  --> $DIR/issue-43197.rs:20:20
+   |
+LL |     const X: u32 = 0-1;
+   |                    ^^^
+   |
+note: lint level defined here
+  --> $DIR/issue-43197.rs:11:9
+   |
+LL | #![warn(const_err)]
+   |         ^^^^^^^^^
+
+warning: this constant cannot be used
+  --> $DIR/issue-43197.rs:20:5
+   |
+LL |     const X: u32 = 0-1;
+   |     ^^^^^^^^^^^^^^^---^
+   |                    |
+   |                    attempt to subtract with overflow
+
+warning: attempt to subtract with overflow
+  --> $DIR/issue-43197.rs:23:24
+   |
+LL |     const Y: u32 = foo(0-1);
+   |                        ^^^
+
+warning: this constant cannot be used
+  --> $DIR/issue-43197.rs:23:5
+   |
+LL |     const Y: u32 = foo(0-1);
+   |     ^^^^^^^^^^^^^^^^^^^---^^
+   |                        |
+   |                        attempt to subtract with overflow
+
+warning: referenced constant
+  --> $DIR/issue-43197.rs:26:23
+   |
+LL |     const X: u32 = 0-1;
+   |                    --- attempt to subtract with overflow
+...
+LL |     println!("{} {}", X, Y);
+   |                       ^
+
+warning: this expression will panic at runtime
+  --> $DIR/issue-43197.rs:26:23
+   |
+LL |     println!("{} {}", X, Y);
+   |                       ^ referenced constant has errors
+
+warning: referenced constant
+  --> $DIR/issue-43197.rs:26:26
+   |
+LL |     const Y: u32 = foo(0-1);
+   |                        --- attempt to subtract with overflow
+...
+LL |     println!("{} {}", X, Y);
+   |                          ^
+
+warning: this expression will panic at runtime
+  --> $DIR/issue-43197.rs:26:26
+   |
+LL |     println!("{} {}", X, Y);
+   |                          ^ referenced constant has errors
+
+error[E0080]: referenced constant
+  --> $DIR/issue-43197.rs:26:5
+   |
+LL |     const X: u32 = 0-1;
+   |                    --- attempt to subtract with overflow
+...
+LL |     println!("{} {}", X, Y);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error[E0080]: erroneous constant used
+  --> $DIR/issue-43197.rs:26:5
+   |
+LL |     println!("{} {}", X, Y);
+   |     ^^^^^^^^^^^^^^^^^^-^^^^^
+   |                       |
+   |                       referenced constant has errors
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error[E0080]: referenced constant
+  --> $DIR/issue-43197.rs:26:26
+   |
+LL |     const Y: u32 = foo(0-1);
+   |                        --- attempt to subtract with overflow
+...
+LL |     println!("{} {}", X, Y);
+   |                          ^
+
+error[E0080]: erroneous constant used
+  --> $DIR/issue-43197.rs:26:26
+   |
+LL |     println!("{} {}", X, Y);
+   |                          ^ referenced constant has errors
+
+error[E0080]: referenced constant
+  --> $DIR/issue-43197.rs:26:23
+   |
+LL |     const X: u32 = 0-1;
+   |                    --- attempt to subtract with overflow
+...
+LL |     println!("{} {}", X, Y);
+   |                       ^
+
+error[E0080]: erroneous constant used
+  --> $DIR/issue-43197.rs:26:23
+   |
+LL |     println!("{} {}", X, Y);
+   |                       ^ referenced constant has errors
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/const-eval/issue-43197.rs b/src/test/ui/const-eval/issue-43197.rs
index 7ec100e411b..03aa65eb274 100644
--- a/src/test/ui/const-eval/issue-43197.rs
+++ b/src/test/ui/const-eval/issue-43197.rs
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-pass
 #![warn(const_err)]
 
 #![feature(const_fn)]
@@ -25,6 +24,12 @@ fn main() {
     //~^ WARN attempt to subtract with overflow
     //~| WARN this constant cannot be used
     println!("{} {}", X, Y);
-    //~^ WARN constant evaluation error
-    //~| WARN constant evaluation error
+    //~^ WARN this expression will panic at runtime
+    //~| WARN this expression will panic at runtime
+    //~| ERROR erroneous constant used
+    //~| ERROR erroneous constant used
+    //~| ERROR E0080
+    //~| ERROR E0080
+    //~| WARN referenced constant
+    //~| WARN referenced constant
 }
diff --git a/src/test/ui/const-eval/issue-43197.stderr b/src/test/ui/const-eval/issue-43197.stderr
index d0e13d5657e..071d8787307 100644
--- a/src/test/ui/const-eval/issue-43197.stderr
+++ b/src/test/ui/const-eval/issue-43197.stderr
@@ -1,42 +1,97 @@
 warning: attempt to subtract with overflow
-  --> $DIR/issue-43197.rs:21:20
+  --> $DIR/issue-43197.rs:20:20
    |
 LL |     const X: u32 = 0-1;
    |                    ^^^
    |
 note: lint level defined here
-  --> $DIR/issue-43197.rs:12:9
+  --> $DIR/issue-43197.rs:11:9
    |
 LL | #![warn(const_err)]
    |         ^^^^^^^^^
 
 warning: this constant cannot be used
-  --> $DIR/issue-43197.rs:21:5
+  --> $DIR/issue-43197.rs:20:5
    |
 LL |     const X: u32 = 0-1;
-   |     ^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
+   |     ^^^^^^^^^^^^^^^---^
+   |                    |
+   |                    attempt to subtract with overflow
 
 warning: attempt to subtract with overflow
-  --> $DIR/issue-43197.rs:24:24
+  --> $DIR/issue-43197.rs:23:24
    |
 LL |     const Y: u32 = foo(0-1);
    |                        ^^^
 
 warning: this constant cannot be used
-  --> $DIR/issue-43197.rs:24:5
+  --> $DIR/issue-43197.rs:23:5
    |
 LL |     const Y: u32 = foo(0-1);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
+   |     ^^^^^^^^^^^^^^^^^^^---^^
+   |                        |
+   |                        attempt to subtract with overflow
 
-warning: constant evaluation error
-  --> $DIR/issue-43197.rs:27:23
+warning: referenced constant
+  --> $DIR/issue-43197.rs:26:23
+   |
+LL |     const X: u32 = 0-1;
+   |                    --- attempt to subtract with overflow
+...
+LL |     println!("{} {}", X, Y);
+   |                       ^
+
+warning: this expression will panic at runtime
+  --> $DIR/issue-43197.rs:26:23
    |
 LL |     println!("{} {}", X, Y);
    |                       ^ referenced constant has errors
 
-warning: constant evaluation error
-  --> $DIR/issue-43197.rs:27:26
+warning: referenced constant
+  --> $DIR/issue-43197.rs:26:26
+   |
+LL |     const Y: u32 = foo(0-1);
+   |                        --- attempt to subtract with overflow
+...
+LL |     println!("{} {}", X, Y);
+   |                          ^
+
+warning: this expression will panic at runtime
+  --> $DIR/issue-43197.rs:26:26
    |
 LL |     println!("{} {}", X, Y);
    |                          ^ referenced constant has errors
 
+error[E0080]: referenced constant
+  --> $DIR/issue-43197.rs:26:26
+   |
+LL |     const Y: u32 = foo(0-1);
+   |                        --- attempt to subtract with overflow
+...
+LL |     println!("{} {}", X, Y);
+   |                          ^
+
+error[E0080]: erroneous constant used
+  --> $DIR/issue-43197.rs:26:26
+   |
+LL |     println!("{} {}", X, Y);
+   |                          ^ referenced constant has errors
+
+error[E0080]: referenced constant
+  --> $DIR/issue-43197.rs:26:23
+   |
+LL |     const X: u32 = 0-1;
+   |                    --- attempt to subtract with overflow
+...
+LL |     println!("{} {}", X, Y);
+   |                       ^
+
+error[E0080]: erroneous constant used
+  --> $DIR/issue-43197.rs:26:23
+   |
+LL |     println!("{} {}", X, Y);
+   |                       ^ referenced constant has errors
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/const-eval/issue-44578.nll.stderr b/src/test/ui/const-eval/issue-44578.nll.stderr
new file mode 100644
index 00000000000..ad4f08966c0
--- /dev/null
+++ b/src/test/ui/const-eval/issue-44578.nll.stderr
@@ -0,0 +1,39 @@
+error[E0080]: referenced constant
+  --> $DIR/issue-44578.rs:35:5
+   |
+LL |     const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize];
+   |                        ------------------------------------ index out of bounds: the len is 1 but the index is 1
+...
+LL |     println!("{}", <Bar<u16, u8> as Foo>::AMT);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error[E0080]: erroneous constant used
+  --> $DIR/issue-44578.rs:35:5
+   |
+LL |     println!("{}", <Bar<u16, u8> as Foo>::AMT);
+   |     ^^^^^^^^^^^^^^^--------------------------^^
+   |                    |
+   |                    referenced constant has errors
+   |
+   = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
+
+error[E0080]: referenced constant
+  --> $DIR/issue-44578.rs:35:20
+   |
+LL |     const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize];
+   |                        ------------------------------------ index out of bounds: the len is 1 but the index is 1
+...
+LL |     println!("{}", <Bar<u16, u8> as Foo>::AMT);
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0080]: erroneous constant used
+  --> $DIR/issue-44578.rs:35:20
+   |
+LL |     println!("{}", <Bar<u16, u8> as Foo>::AMT);
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/const-eval/issue-44578.rs b/src/test/ui/const-eval/issue-44578.rs
index 4133a8864f6..59ac4ab311c 100644
--- a/src/test/ui/const-eval/issue-44578.rs
+++ b/src/test/ui/const-eval/issue-44578.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-pass
-#![warn(const_err)]
+#![allow(const_err)]
 
 trait Foo {
     const AMT: usize;
@@ -33,6 +32,7 @@ impl Foo for u16 {
 }
 
 fn main() {
-    println!("{}", <Bar<u16, u8> as Foo>::AMT); //~ WARN const_err
-    //~^ WARN const_err
+    println!("{}", <Bar<u16, u8> as Foo>::AMT);
+    //~^ ERROR erroneous constant used
+    //~| ERROR E0080
 }
diff --git a/src/test/ui/const-eval/issue-44578.stderr b/src/test/ui/const-eval/issue-44578.stderr
index ce6ff86610a..28a723a069e 100644
--- a/src/test/ui/const-eval/issue-44578.stderr
+++ b/src/test/ui/const-eval/issue-44578.stderr
@@ -1,18 +1,18 @@
-warning: constant evaluation error
-  --> $DIR/issue-44578.rs:36:20
+error[E0080]: referenced constant
+  --> $DIR/issue-44578.rs:35:20
    |
-LL |     println!("{}", <Bar<u16, u8> as Foo>::AMT); //~ WARN const_err
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
-   |
-note: lint level defined here
-  --> $DIR/issue-44578.rs:12:9
-   |
-LL | #![warn(const_err)]
-   |         ^^^^^^^^^
+LL |     const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize];
+   |                        ------------------------------------ index out of bounds: the len is 1 but the index is 1
+...
+LL |     println!("{}", <Bar<u16, u8> as Foo>::AMT);
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: constant evaluation error
-  --> $DIR/issue-44578.rs:36:20
+error[E0080]: erroneous constant used
+  --> $DIR/issue-44578.rs:35:20
    |
-LL |     println!("{}", <Bar<u16, u8> as Foo>::AMT); //~ WARN const_err
+LL |     println!("{}", <Bar<u16, u8> as Foo>::AMT);
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
 
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/const-eval/issue-50814-2.rs b/src/test/ui/const-eval/issue-50814-2.rs
new file mode 100644
index 00000000000..af627ee5fbe
--- /dev/null
+++ b/src/test/ui/const-eval/issue-50814-2.rs
@@ -0,0 +1,43 @@
+// Copyright 2018 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.
+
+trait C {
+    const BOO: usize;
+}
+
+trait Foo<T> {
+    const BAR: usize;
+}
+
+struct A<T>(T);
+
+impl<T: C> Foo<T> for A<T> {
+    const BAR: usize = [5, 6, 7][T::BOO];
+}
+
+fn foo<T: C>() -> &'static usize {
+    &<A<T> as Foo<T>>::BAR //~ ERROR erroneous constant used
+//~| ERROR E0080
+}
+
+impl C for () {
+    const BOO: usize = 42;
+}
+
+impl C for u32 {
+    const BOO: usize = 1;
+}
+
+fn main() {
+    println!("{:x}", foo::<()>() as *const usize as usize);
+    println!("{:x}", foo::<u32>() as *const usize as usize);
+    println!("{:x}", foo::<()>());
+    println!("{:x}", foo::<u32>());
+}
diff --git a/src/test/ui/const-eval/issue-50814-2.stderr b/src/test/ui/const-eval/issue-50814-2.stderr
new file mode 100644
index 00000000000..3c59cb0e2bc
--- /dev/null
+++ b/src/test/ui/const-eval/issue-50814-2.stderr
@@ -0,0 +1,20 @@
+error[E0080]: referenced constant
+  --> $DIR/issue-50814-2.rs:26:5
+   |
+LL |     const BAR: usize = [5, 6, 7][T::BOO];
+   |                        ----------------- index out of bounds: the len is 3 but the index is 42
+...
+LL |     &<A<T> as Foo<T>>::BAR //~ ERROR erroneous constant used
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0080]: erroneous constant used
+  --> $DIR/issue-50814-2.rs:26:5
+   |
+LL |     &<A<T> as Foo<T>>::BAR //~ ERROR erroneous constant used
+   |     ^---------------------
+   |      |
+   |      referenced constant has errors
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/const-eval/issue-50814.rs b/src/test/ui/const-eval/issue-50814.rs
new file mode 100644
index 00000000000..8f2752453b5
--- /dev/null
+++ b/src/test/ui/const-eval/issue-50814.rs
@@ -0,0 +1,33 @@
+// Copyright 2018 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.
+
+trait Unsigned {
+    const MAX: u8;
+}
+
+struct U8(u8);
+impl Unsigned for U8 {
+    const MAX: u8 = 0xff;
+}
+
+struct Sum<A,B>(A,B);
+
+impl<A: Unsigned, B: Unsigned> Unsigned for Sum<A,B> {
+    const MAX: u8 = A::MAX + B::MAX;
+}
+
+fn foo<T>(_: T) -> &'static u8 {
+    &Sum::<U8,U8>::MAX //~ ERROR erroneous constant used
+//~| ERROR E0080
+}
+
+fn main() {
+    foo(0);
+}
diff --git a/src/test/ui/const-eval/issue-50814.stderr b/src/test/ui/const-eval/issue-50814.stderr
new file mode 100644
index 00000000000..145279ccc03
--- /dev/null
+++ b/src/test/ui/const-eval/issue-50814.stderr
@@ -0,0 +1,20 @@
+error[E0080]: referenced constant
+  --> $DIR/issue-50814.rs:27:5
+   |
+LL |     const MAX: u8 = A::MAX + B::MAX;
+   |                     --------------- attempt to add with overflow
+...
+LL |     &Sum::<U8,U8>::MAX //~ ERROR erroneous constant used
+   |     ^^^^^^^^^^^^^^^^^^
+
+error[E0080]: erroneous constant used
+  --> $DIR/issue-50814.rs:27:5
+   |
+LL |     &Sum::<U8,U8>::MAX //~ ERROR erroneous constant used
+   |     ^-----------------
+   |      |
+   |      referenced constant has errors
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/const-eval/promoted_const_fn_fail.rs b/src/test/ui/const-eval/promoted_const_fn_fail.rs
index 5ced2c9dd8f..4888ed6e8dc 100644
--- a/src/test/ui/const-eval/promoted_const_fn_fail.rs
+++ b/src/test/ui/const-eval/promoted_const_fn_fail.rs
@@ -23,8 +23,8 @@ const fn bar() -> u8 {
         // is run on a system whose pointers need more
         // than 8 bits
         Bar { a: &42 }.b as u8
-        //~^ constant evaluation error
-        //~| constant evaluation error
+        //~^ ERROR this expression will panic at runtime
+        //~| ERROR this expression will panic at runtime
     }
 }
 
diff --git a/src/test/ui/const-eval/promoted_const_fn_fail.stderr b/src/test/ui/const-eval/promoted_const_fn_fail.stderr
index f910705bb7b..d805e1a27c9 100644
--- a/src/test/ui/const-eval/promoted_const_fn_fail.stderr
+++ b/src/test/ui/const-eval/promoted_const_fn_fail.stderr
@@ -1,4 +1,4 @@
-error: constant evaluation error
+error: this expression will panic at runtime
   --> $DIR/promoted_const_fn_fail.rs:25:9
    |
 LL |         Bar { a: &42 }.b as u8
@@ -9,23 +9,12 @@ note: lint level defined here
    |
 LL | #![deny(const_err)]
    |         ^^^^^^^^^
-note: inside call to `bar`
-  --> $DIR/promoted_const_fn_fail.rs:35:28
-   |
-LL |     let x: &'static u8 = &(bar() + 1);
-   |                            ^^^^^
 
-error: constant evaluation error
+error: this expression will panic at runtime
   --> $DIR/promoted_const_fn_fail.rs:25:9
    |
 LL |         Bar { a: &42 }.b as u8
    |         ^^^^^^^^^^^^^^^^^^^^^^ a raw memory access tried to access part of a pointer value as raw bytes
-   |
-note: inside call to `bar`
-  --> $DIR/promoted_const_fn_fail.rs:35:28
-   |
-LL |     let x: &'static u8 = &(bar() + 1);
-   |                            ^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/const-eval/promoted_errors.stderr b/src/test/ui/const-eval/promoted_errors.stderr
index 683ee5375fb..a4c1c48a03d 100644
--- a/src/test/ui/const-eval/promoted_errors.stderr
+++ b/src/test/ui/const-eval/promoted_errors.stderr
@@ -1,4 +1,4 @@
-warning: constant evaluation error
+warning: this expression will panic at runtime
   --> $DIR/promoted_errors.rs:17:14
    |
 LL |     let _x = 0u32 - 1;
@@ -16,7 +16,7 @@ warning: attempt to divide by zero
 LL |     println!("{}", 1/(1-1));
    |                    ^^^^^^^
 
-warning: constant evaluation error
+warning: this expression will panic at runtime
   --> $DIR/promoted_errors.rs:19:20
    |
 LL |     println!("{}", 1/(1-1));
@@ -28,13 +28,13 @@ warning: attempt to divide by zero
 LL |     let _x = 1/(1-1);
    |              ^^^^^^^
 
-warning: constant evaluation error
+warning: this expression will panic at runtime
   --> $DIR/promoted_errors.rs:22:14
    |
 LL |     let _x = 1/(1-1);
    |              ^^^^^^^ attempt to divide by zero
 
-warning: constant evaluation error
+warning: this expression will panic at runtime
   --> $DIR/promoted_errors.rs:25:20
    |
 LL |     println!("{}", 1/(false as u32));
diff --git a/src/test/ui/const-eval/pub_const_err.stderr b/src/test/ui/const-eval/pub_const_err.stderr
index 068825f1cd3..35228941754 100644
--- a/src/test/ui/const-eval/pub_const_err.stderr
+++ b/src/test/ui/const-eval/pub_const_err.stderr
@@ -14,7 +14,9 @@ warning: this constant cannot be used
   --> $DIR/pub_const_err.rs:16:1
    |
 LL | pub const Z: u32 = 0 - 1;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
+   | ^^^^^^^^^^^^^^^^^^^-----^
+   |                    |
+   |                    attempt to subtract with overflow
 
 warning: attempt to subtract with overflow
   --> $DIR/pub_const_err.rs:20:22
diff --git a/src/test/ui/const-eval/pub_const_err_bin.stderr b/src/test/ui/const-eval/pub_const_err_bin.stderr
index dcb8125fc55..a6db2176011 100644
--- a/src/test/ui/const-eval/pub_const_err_bin.stderr
+++ b/src/test/ui/const-eval/pub_const_err_bin.stderr
@@ -14,7 +14,9 @@ warning: this constant cannot be used
   --> $DIR/pub_const_err_bin.rs:14:1
    |
 LL | pub const Z: u32 = 0 - 1;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
+   | ^^^^^^^^^^^^^^^^^^^-----^
+   |                    |
+   |                    attempt to subtract with overflow
 
 warning: attempt to subtract with overflow
   --> $DIR/pub_const_err_bin.rs:18:22
diff --git a/src/test/ui/const-fn-error.rs b/src/test/ui/const-fn-error.rs
index 17dc9f94fe1..6eda41730b3 100644
--- a/src/test/ui/const-fn-error.rs
+++ b/src/test/ui/const-fn-error.rs
@@ -19,7 +19,6 @@ const fn f(x: usize) -> usize {
     for i in 0..x {
         //~^ ERROR E0015
         //~| ERROR E0019
-        //~| ERROR E0080
         sum += i;
     }
     sum
@@ -27,5 +26,5 @@ const fn f(x: usize) -> usize {
 
 #[allow(unused_variables)]
 fn main() {
-    let a : [i32; f(X)];
+    let a : [i32; f(X)]; //~ ERROR E0080
 }
diff --git a/src/test/ui/const-fn-error.stderr b/src/test/ui/const-fn-error.stderr
index 29edc2756af..cdbf86f42ec 100644
--- a/src/test/ui/const-fn-error.stderr
+++ b/src/test/ui/const-fn-error.stderr
@@ -26,20 +26,16 @@ error[E0019]: constant function contains unimplemented expression type
 LL |     for i in 0..x {
    |              ^^^^
 
-error[E0080]: constant evaluation error
-  --> $DIR/const-fn-error.rs:19:14
+error[E0080]: could not evaluate constant expression
+  --> $DIR/const-fn-error.rs:29:13
    |
 LL |     for i in 0..x {
-   |              ^^^^ calling non-const fn `<I as std::iter::IntoIterator><std::ops::Range<usize>>::into_iter`
+   |              ---- calling non-const fn `<I as std::iter::IntoIterator><std::ops::Range<usize>>::into_iter`
 ...
-LL |     let a : [i32; f(X)];
-   |                   ---- inside call to `f`
-   |
-note: for constant expression here
-  --> $DIR/const-fn-error.rs:30:13
-   |
-LL |     let a : [i32; f(X)];
-   |             ^^^^^^^^^^^
+LL |     let a : [i32; f(X)]; //~ ERROR E0080
+   |             ^^^^^^----^
+   |                   |
+   |                   inside call to `f`
 
 error: aborting due to 5 previous errors
 
diff --git a/src/test/ui/const-len-underflow-separate-spans.rs b/src/test/ui/const-len-underflow-separate-spans.rs
index 453e332a903..20b88657674 100644
--- a/src/test/ui/const-len-underflow-separate-spans.rs
+++ b/src/test/ui/const-len-underflow-separate-spans.rs
@@ -21,4 +21,5 @@ const LEN: usize = ONE - TWO;
 fn main() {
     let a: [i8; LEN] = unimplemented!();
 //~^ ERROR E0080
+//~| ERROR E0080
 }
diff --git a/src/test/ui/const-len-underflow-separate-spans.stderr b/src/test/ui/const-len-underflow-separate-spans.stderr
index 48ff7a81c24..630828ef8f5 100644
--- a/src/test/ui/const-len-underflow-separate-spans.stderr
+++ b/src/test/ui/const-len-underflow-separate-spans.stderr
@@ -12,12 +12,23 @@ error[E0080]: constant evaluation error
 LL | const LEN: usize = ONE - TWO;
    |                    ^^^^^^^^^ attempt to subtract with overflow
 
-error[E0080]: constant evaluation error
-  --> $DIR/const-len-underflow-separate-spans.rs:22:17
+error[E0080]: referenced constant
+  --> $DIR/const-len-underflow-separate-spans.rs:22:12
+   |
+LL | const LEN: usize = ONE - TWO;
+   |                    --------- attempt to subtract with overflow
+...
+LL |     let a: [i8; LEN] = unimplemented!();
+   |            ^^^^^^^^^
+
+error[E0080]: could not evaluate constant expression
+  --> $DIR/const-len-underflow-separate-spans.rs:22:12
    |
 LL |     let a: [i8; LEN] = unimplemented!();
-   |                 ^^^ referenced constant has errors
+   |            ^^^^^---^
+   |                 |
+   |                 referenced constant has errors
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/error-codes/E0080.stderr b/src/test/ui/error-codes/E0080.stderr
index 25ec5c45831..a213c2b1b20 100644
--- a/src/test/ui/error-codes/E0080.stderr
+++ b/src/test/ui/error-codes/E0080.stderr
@@ -6,7 +6,7 @@ LL |     X = (1 << 500), //~ ERROR E0080
    |
    = note: #[deny(exceeding_bitshifts)] on by default
 
-error[E0080]: constant evaluation error
+error[E0080]: could not evaluate enum discriminant
   --> $DIR/E0080.rs:12:9
    |
 LL |     X = (1 << 500), //~ ERROR E0080
@@ -20,13 +20,13 @@ LL |     Y = (1 / 0) //~ ERROR E0080
    |
    = note: #[deny(const_err)] on by default
 
-error: constant evaluation error
+error: this expression will panic at runtime
   --> $DIR/E0080.rs:14:9
    |
 LL |     Y = (1 / 0) //~ ERROR E0080
    |         ^^^^^^^ attempt to divide by zero
 
-error[E0080]: constant evaluation error
+error[E0080]: could not evaluate enum discriminant
   --> $DIR/E0080.rs:14:9
    |
 LL |     Y = (1 / 0) //~ ERROR E0080
diff --git a/src/test/ui/infinite-recursion-const-fn.rs b/src/test/ui/infinite-recursion-const-fn.rs
index f98074bc554..4f1f6721450 100644
--- a/src/test/ui/infinite-recursion-const-fn.rs
+++ b/src/test/ui/infinite-recursion-const-fn.rs
@@ -11,8 +11,8 @@
 //https://github.com/rust-lang/rust/issues/31364
 
 #![feature(const_fn)]
-const fn a() -> usize { b() } //~ ERROR constant evaluation error
+const fn a() -> usize { b() }
 const fn b() -> usize { a() }
-const ARR: [i32; a()] = [5; 6];
+const ARR: [i32; a()] = [5; 6]; //~ ERROR could not evaluate constant expression
 
 fn main(){}
diff --git a/src/test/ui/infinite-recursion-const-fn.stderr b/src/test/ui/infinite-recursion-const-fn.stderr
index 81717fe1f09..fb7c1be7541 100644
--- a/src/test/ui/infinite-recursion-const-fn.stderr
+++ b/src/test/ui/infinite-recursion-const-fn.stderr
@@ -1,8 +1,8 @@
-error[E0080]: constant evaluation error
-  --> $DIR/infinite-recursion-const-fn.rs:14:25
+error[E0080]: could not evaluate constant expression
+  --> $DIR/infinite-recursion-const-fn.rs:16:1
    |
-LL | const fn a() -> usize { b() } //~ ERROR constant evaluation error
-   |                         ^^^
+LL | const fn a() -> usize { b() }
+   |                         ---
    |                         |
    |                         reached the configured maximum number of stack frames
    |                         inside call to `b`
@@ -58,14 +58,10 @@ LL | const fn b() -> usize { a() }
    |                         inside call to `a`
    |                         inside call to `a`
    |                         inside call to `a`
-LL | const ARR: [i32; a()] = [5; 6];
-   |                  --- inside call to `a`
-   |
-note: for constant expression here
-  --> $DIR/infinite-recursion-const-fn.rs:16:1
-   |
-LL | const ARR: [i32; a()] = [5; 6];
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | const ARR: [i32; a()] = [5; 6]; //~ ERROR could not evaluate constant expression
+   | ^^^^^^^^^^^^^^^^^---^^^^^^^^^^^
+   |                  |
+   |                  inside call to `a`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/type-dependent-def-issue-49241.rs b/src/test/ui/type-dependent-def-issue-49241.rs
index 64264999fd2..db27ae89e69 100644
--- a/src/test/ui/type-dependent-def-issue-49241.rs
+++ b/src/test/ui/type-dependent-def-issue-49241.rs
@@ -11,5 +11,5 @@
 fn main() {
     let v = vec![0];
     const l: usize = v.count(); //~ ERROR can't capture dynamic environment in a fn item
-    let s: [u32; l] = v.into_iter().collect(); //~ ERROR constant evaluation error
+    let s: [u32; l] = v.into_iter().collect();
 }
diff --git a/src/test/ui/type-dependent-def-issue-49241.stderr b/src/test/ui/type-dependent-def-issue-49241.stderr
index f00edccae5d..361d28f274f 100644
--- a/src/test/ui/type-dependent-def-issue-49241.stderr
+++ b/src/test/ui/type-dependent-def-issue-49241.stderr
@@ -6,13 +6,6 @@ LL |     const l: usize = v.count(); //~ ERROR can't capture dynamic environment
    |
    = help: use the `|| { ... }` closure form instead
 
-error[E0080]: constant evaluation error
-  --> $DIR/type-dependent-def-issue-49241.rs:14:18
-   |
-LL |     let s: [u32; l] = v.into_iter().collect(); //~ ERROR constant evaluation error
-   |                  ^ encountered constants with type errors, stopping evaluation
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors occurred: E0080, E0434.
-For more information about an error, try `rustc --explain E0080`.
+For more information about this error, try `rustc --explain E0434`.