From 5c0d1355f261efd624e0f7755a87e46d954771d3 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Sat, 2 Jun 2018 23:38:57 +0200 Subject: [PATCH 1/8] Refactor the const eval diagnostic API --- src/librustc/ich/impls_ty.rs | 1 + src/librustc/lint/context.rs | 3 + src/librustc/middle/const_val.rs | 115 +++++++++++------- src/librustc/mir/interpret/error.rs | 36 ++++++ src/librustc/traits/error_reporting.rs | 9 +- src/librustc/ty/mod.rs | 8 +- src/librustc_codegen_llvm/mir/constant.rs | 5 +- src/librustc_codegen_llvm/mir/operand.rs | 5 +- src/librustc_lint/builtin.rs | 19 +-- src/librustc_mir/hair/cx/expr.rs | 2 +- src/librustc_mir/hair/pattern/check_match.rs | 4 +- src/librustc_mir/hair/pattern/mod.rs | 5 +- src/librustc_mir/interpret/const_eval.rs | 50 +++----- src/librustc_mir/interpret/eval_context.rs | 88 ++------------ src/librustc_mir/interpret/mod.rs | 1 - src/librustc_mir/monomorphize/collector.rs | 10 +- src/librustc_mir/transform/const_prop.rs | 101 +++++++++------ src/librustc_typeck/check/mod.rs | 5 +- src/test/compile-fail/const-array-oob.rs | 2 +- src/test/compile-fail/const-err-early.rs | 2 +- src/test/compile-fail/const-err-multi.rs | 2 +- src/test/compile-fail/const-err.rs | 1 + .../compile-fail/const-integer-bool-ops.rs | 10 -- .../const-len-underflow-subspans.rs | 2 +- src/test/compile-fail/const-match-check.rs | 1 - src/test/compile-fail/const-tup-index-span.rs | 1 - src/test/compile-fail/eval-enum.rs | 8 +- src/test/compile-fail/issue-43105.rs | 2 +- src/test/compile-fail/issue-8460-const.rs | 40 +++--- src/test/ui/const-eval-overflow-2.rs | 2 +- src/test/ui/const-eval-overflow-2.stderr | 11 +- src/test/ui/const-eval-overflow-4.rs | 4 +- src/test/ui/const-eval-overflow-4.stderr | 15 ++- .../const-eval/conditional_array_execution.rs | 2 +- .../conditional_array_execution.stderr | 6 +- src/test/ui/const-eval/issue-43197.rs | 4 +- src/test/ui/const-eval/issue-43197.stderr | 12 +- src/test/ui/const-eval/issue-44578.stderr | 4 +- .../ui/const-eval/promoted_const_fn_fail.rs | 4 +- .../const-eval/promoted_const_fn_fail.stderr | 15 +-- src/test/ui/const-eval/promoted_errors.stderr | 8 +- src/test/ui/const-eval/pub_const_err.stderr | 4 +- .../ui/const-eval/pub_const_err_bin.stderr | 4 +- src/test/ui/const-fn-error.rs | 3 +- src/test/ui/const-fn-error.stderr | 18 ++- .../const-len-underflow-separate-spans.stderr | 8 +- src/test/ui/error-codes/E0080.stderr | 6 +- src/test/ui/infinite-recursion-const-fn.rs | 4 +- .../ui/infinite-recursion-const-fn.stderr | 20 ++- src/test/ui/type-dependent-def-issue-49241.rs | 2 +- .../ui/type-dependent-def-issue-49241.stderr | 11 +- 51 files changed, 354 insertions(+), 351 deletions(-) diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 04e57883c77..e1e5bc58952 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 }); 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..d4ec71bc6c4 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::{self, layout}; 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; @@ -52,6 +54,7 @@ pub enum ErrKind<'tcx> { pub struct FrameInfo { pub span: Span, pub location: String, + pub lint_root: Option, } #[derive(Clone, Debug)] @@ -100,64 +103,86 @@ 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> { - 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)); - } - } - } - - if !primary_span.contains(self.span) { - diag.span_note(primary_span, - &format!("for {} here", primary_kind)); + 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(); } } - 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, _) => { + 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(); + } + } + + fn struct_generic( + &self, + tcx: TyCtxtAt<'a, 'gcx, 'tcx>, + message: &str, + lint_root: Option, + as_err: bool, + ) -> Option> { + 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, + _ => (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..1b7c8bdc8a3 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -16,6 +16,42 @@ pub struct EvalError<'tcx> { pub backtrace: Option, } +impl<'tcx> EvalError<'tcx> { + pub fn print_backtrace(&mut self) { + if let Some(ref mut backtrace) = self.backtrace { + use std::fmt::Write; + 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, "\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, "").unwrap(); + } + if let Some(line) = symbol.lineno() { + write!(trace_text, ":{}\n", line).unwrap(); + } else { + write!(trace_text, "\n").unwrap(); + } + } + } + error!("{}", trace_text); + } + } +} + impl<'tcx> From> for EvalError<'tcx> { fn from(kind: EvalErrorKind<'tcx, u64>) -> Self { let backtrace = match env::var("MIRI_BACKTRACE") { 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/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_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..17df184920c 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") } } } @@ -579,15 +565,17 @@ pub fn const_eval_provider<'a, 'tcx>( } 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); - } + err.print_backtrace(); 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..4c03046f7b1 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -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; @@ -1626,7 +1626,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,84 +1644,22 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M } else { instance.to_string() }; - frames.push(FrameInfo { span, location }); + let block = &mir.basic_blocks()[block]; + let source_info = if stmt < block.statements.len() { + block.statements[stmt].source_info + } else { + block.terminator().source_info + }; + 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 report(&self, e: &mut EvalError, as_err: bool, explicit_span: Option) { - 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, "\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, "").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") - } 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", - ) - }; - 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()); - } - } - pub fn sign_extend(&self, value: u128, ty: Ty<'tcx>) -> EvalResult<'tcx, u128> { super::sign_extend(self.tcx.tcx, value, ty) } 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..54221239253 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", + ); } } } @@ -1236,7 +1239,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..83b4ea54aab 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( &mut self, - span: Span, + source_info: SourceInfo, f: F ) -> Option 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> { + fn const_eval(&mut self, cid: GlobalId<'tcx>, source_info: SourceInfo) -> Option> { 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> { + fn eval_constant( + &mut self, + c: &Constant<'tcx>, + source_info: SourceInfo, + ) -> Option> { 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) @@ -225,9 +251,9 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> { } } - fn eval_operand(&mut self, op: &Operand<'tcx>) -> Option> { + fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option> { match *op { - Operand::Constant(ref c) => self.eval_constant(c), + Operand::Constant(ref c) => self.eval_constant(c, source_info), Operand::Move(ref place) | Operand::Copy(ref place) => self.eval_place(place), } } @@ -243,10 +269,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 +305,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 +327,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 +358,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 +374,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 +454,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 +490,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 +527,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..277a92e8314 100644 --- a/src/test/compile-fail/const-err-multi.rs +++ b/src/test/compile-fail/const-err-multi.rs @@ -13,7 +13,7 @@ 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 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) { // 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.rs b/src/test/ui/const-eval/conditional_array_execution.rs index 8952a8386d7..daeeae513d9 100644 --- a/src/test/ui/const-eval/conditional_array_execution.rs +++ b/src/test/ui/const-eval/conditional_array_execution.rs @@ -19,5 +19,5 @@ 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 } diff --git a/src/test/ui/const-eval/conditional_array_execution.stderr b/src/test/ui/const-eval/conditional_array_execution.stderr index 5cf73b9fad6..00b39d08eaf 100644 --- a/src/test/ui/const-eval/conditional_array_execution.stderr +++ b/src/test/ui/const-eval/conditional_array_execution.stderr @@ -14,9 +14,11 @@ warning: this constant cannot be used --> $DIR/conditional_array_execution.rs:16: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 +warning: this expression will panic at runtime --> $DIR/conditional_array_execution.rs:21:20 | LL | println!("{}", FOO); diff --git a/src/test/ui/const-eval/issue-43197.rs b/src/test/ui/const-eval/issue-43197.rs index 7ec100e411b..df352adea63 100644 --- a/src/test/ui/const-eval/issue-43197.rs +++ b/src/test/ui/const-eval/issue-43197.rs @@ -25,6 +25,6 @@ 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 } diff --git a/src/test/ui/const-eval/issue-43197.stderr b/src/test/ui/const-eval/issue-43197.stderr index d0e13d5657e..412d97883f1 100644 --- a/src/test/ui/const-eval/issue-43197.stderr +++ b/src/test/ui/const-eval/issue-43197.stderr @@ -14,7 +14,9 @@ warning: this constant cannot be used --> $DIR/issue-43197.rs:21: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 @@ -26,15 +28,17 @@ warning: this constant cannot be used --> $DIR/issue-43197.rs:24:5 | LL | const Y: u32 = foo(0-1); - | ^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow + | ^^^^^^^^^^^^^^^^^^^---^^ + | | + | attempt to subtract with overflow -warning: constant evaluation error +warning: this expression will panic at runtime --> $DIR/issue-43197.rs:27:23 | LL | println!("{} {}", X, Y); | ^ referenced constant has errors -warning: constant evaluation error +warning: this expression will panic at runtime --> $DIR/issue-43197.rs:27:26 | LL | println!("{} {}", X, Y); diff --git a/src/test/ui/const-eval/issue-44578.stderr b/src/test/ui/const-eval/issue-44578.stderr index ce6ff86610a..3632a9baea1 100644 --- a/src/test/ui/const-eval/issue-44578.stderr +++ b/src/test/ui/const-eval/issue-44578.stderr @@ -1,4 +1,4 @@ -warning: constant evaluation error +warning: this expression will panic at runtime --> $DIR/issue-44578.rs:36:20 | LL | println!("{}", as Foo>::AMT); //~ WARN const_err @@ -10,7 +10,7 @@ note: lint level defined here LL | #![warn(const_err)] | ^^^^^^^^^ -warning: constant evaluation error +warning: this expression will panic at runtime --> $DIR/issue-44578.rs:36:20 | LL | println!("{}", as Foo>::AMT); //~ WARN const_err 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 `>::into_iter` + | ---- calling non-const fn `>::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.stderr b/src/test/ui/const-len-underflow-separate-spans.stderr index 48ff7a81c24..09a68a40b3a 100644 --- a/src/test/ui/const-len-underflow-separate-spans.stderr +++ b/src/test/ui/const-len-underflow-separate-spans.stderr @@ -12,11 +12,13 @@ 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]: 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 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 previous error -error: aborting due to 2 previous errors - -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`. From 9cb47de81337482b226cde3a2f59594ed78412d1 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Sun, 3 Jun 2018 02:04:20 +0200 Subject: [PATCH 2/8] Referring to erroneous constants in promoteds must abort the build --- src/librustc_mir/monomorphize/collector.rs | 16 ++++- .../conditional_array_execution.nll.stderr | 45 ++++++++++++ .../const-eval/conditional_array_execution.rs | 2 +- .../conditional_array_execution.stderr | 17 +++-- src/test/ui/const-eval/issue-43197.nll.stderr | 71 +++++++++++++++++++ src/test/ui/const-eval/issue-43197.rs | 3 +- src/test/ui/const-eval/issue-43197.stderr | 29 ++++++-- src/test/ui/const-eval/issue-44578.nll.stderr | 19 +++++ src/test/ui/const-eval/issue-44578.rs | 7 +- src/test/ui/const-eval/issue-44578.stderr | 21 ++---- src/test/ui/const-eval/issue-50814-2.rs | 42 +++++++++++ src/test/ui/const-eval/issue-50814-2.stderr | 11 +++ src/test/ui/const-eval/issue-50814.rs | 32 +++++++++ src/test/ui/const-eval/issue-50814.stderr | 11 +++ 14 files changed, 292 insertions(+), 34 deletions(-) create mode 100644 src/test/ui/const-eval/conditional_array_execution.nll.stderr create mode 100644 src/test/ui/const-eval/issue-43197.nll.stderr create mode 100644 src/test/ui/const-eval/issue-44578.nll.stderr create mode 100644 src/test/ui/const-eval/issue-50814-2.rs create mode 100644 src/test/ui/const-eval/issue-50814-2.stderr create mode 100644 src/test/ui/const-eval/issue-50814.rs create mode 100644 src/test/ui/const-eval/issue-50814.stderr diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 54221239253..4f3adaaae27 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -1190,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", + ); + } + } + }, } } } 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..a35252c4789 --- /dev/null +++ b/src/test/ui/const-eval/conditional_array_execution.nll.stderr @@ -0,0 +1,45 @@ +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: this expression will panic at runtime + --> $DIR/conditional_array_execution.rs:20:20 + | +LL | println!("{}", FOO); + | ^^^ referenced constant has errors + +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]: 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/conditional_array_execution.rs b/src/test/ui/const-eval/conditional_array_execution.rs index daeeae513d9..055224d2731 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; @@ -20,4 +19,5 @@ const FOO: u32 = [X - Y, Y - X][(X < Y) as usize]; fn main() { println!("{}", FOO); //~^ WARN this expression will panic at runtime + //~| ERROR erroneous constant used } diff --git a/src/test/ui/const-eval/conditional_array_execution.stderr b/src/test/ui/const-eval/conditional_array_execution.stderr index 00b39d08eaf..f396c8f0444 100644 --- a/src/test/ui/const-eval/conditional_array_execution.stderr +++ b/src/test/ui/const-eval/conditional_array_execution.stderr @@ -1,17 +1,17 @@ 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]; | ^^^^^^^^^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -19,8 +19,17 @@ LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize]; | attempt to subtract with overflow warning: this expression will panic at runtime - --> $DIR/conditional_array_execution.rs:21:20 + --> $DIR/conditional_array_execution.rs:20:20 | LL | println!("{}", FOO); | ^^^ referenced constant has errors +error[E0080]: erroneous constant used + --> $DIR/conditional_array_execution.rs:20:20 + | +LL | println!("{}", FOO); + | ^^^ referenced constant has errors + +error: aborting due to previous error + +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..416967613f0 --- /dev/null +++ b/src/test/ui/const-eval/issue-43197.nll.stderr @@ -0,0 +1,71 @@ +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: this expression will panic at runtime + --> $DIR/issue-43197.rs:26:23 + | +LL | println!("{} {}", X, Y); + | ^ referenced constant has errors + +warning: this expression will panic at runtime + --> $DIR/issue-43197.rs:26:26 + | +LL | println!("{} {}", X, Y); + | ^ referenced constant has errors + +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]: erroneous constant used + --> $DIR/issue-43197.rs:26:26 + | +LL | println!("{} {}", X, Y); + | ^ referenced constant has errors + +error[E0080]: erroneous constant used + --> $DIR/issue-43197.rs:26:23 + | +LL | println!("{} {}", X, Y); + | ^ referenced constant has 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.rs b/src/test/ui/const-eval/issue-43197.rs index df352adea63..f8d820db747 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)] @@ -27,4 +26,6 @@ fn main() { println!("{} {}", X, Y); //~^ WARN this expression will panic at runtime //~| WARN this expression will panic at runtime + //~| ERROR erroneous constant used + //~| ERROR erroneous constant used } diff --git a/src/test/ui/const-eval/issue-43197.stderr b/src/test/ui/const-eval/issue-43197.stderr index 412d97883f1..207523f688f 100644 --- a/src/test/ui/const-eval/issue-43197.stderr +++ b/src/test/ui/const-eval/issue-43197.stderr @@ -1,17 +1,17 @@ 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; | ^^^^^^^^^^^^^^^---^ @@ -19,13 +19,13 @@ LL | const X: u32 = 0-1; | 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); | ^^^^^^^^^^^^^^^^^^^---^^ @@ -33,14 +33,29 @@ LL | const Y: u32 = foo(0-1); | attempt to subtract with overflow warning: this expression will panic at runtime - --> $DIR/issue-43197.rs:27:23 + --> $DIR/issue-43197.rs:26:23 | LL | println!("{} {}", X, Y); | ^ referenced constant has errors warning: this expression will panic at runtime - --> $DIR/issue-43197.rs:27:26 + --> $DIR/issue-43197.rs:26:26 | LL | println!("{} {}", X, Y); | ^ referenced constant has errors +error[E0080]: erroneous constant used + --> $DIR/issue-43197.rs:26:26 + | +LL | println!("{} {}", X, Y); + | ^ referenced constant has errors + +error[E0080]: erroneous constant used + --> $DIR/issue-43197.rs:26:23 + | +LL | println!("{} {}", X, Y); + | ^ 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-44578.nll.stderr b/src/test/ui/const-eval/issue-44578.nll.stderr new file mode 100644 index 00000000000..49587fa0809 --- /dev/null +++ b/src/test/ui/const-eval/issue-44578.nll.stderr @@ -0,0 +1,19 @@ +error[E0080]: erroneous constant used + --> $DIR/issue-44578.rs:35:5 + | +LL | println!("{}", 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]: erroneous constant used + --> $DIR/issue-44578.rs:35:20 + | +LL | println!("{}", 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-44578.rs b/src/test/ui/const-eval/issue-44578.rs index 4133a8864f6..331de4ab661 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,6 @@ impl Foo for u16 { } fn main() { - println!("{}", as Foo>::AMT); //~ WARN const_err - //~^ WARN const_err + println!("{}", as Foo>::AMT); + //~^ ERROR erroneous constant used } diff --git a/src/test/ui/const-eval/issue-44578.stderr b/src/test/ui/const-eval/issue-44578.stderr index 3632a9baea1..42d60c604b8 100644 --- a/src/test/ui/const-eval/issue-44578.stderr +++ b/src/test/ui/const-eval/issue-44578.stderr @@ -1,18 +1,9 @@ -warning: this expression will panic at runtime - --> $DIR/issue-44578.rs:36:20 +error[E0080]: erroneous constant used + --> $DIR/issue-44578.rs:35:20 | -LL | println!("{}", 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)] - | ^^^^^^^^^ - -warning: this expression will panic at runtime - --> $DIR/issue-44578.rs:36:20 - | -LL | println!("{}", as Foo>::AMT); //~ WARN const_err +LL | println!("{}", as Foo>::AMT); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors +error: aborting due to previous error + +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..a90579296cb --- /dev/null +++ b/src/test/ui/const-eval/issue-50814-2.rs @@ -0,0 +1,42 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait C { + const BOO: usize; +} + +trait Foo { + const BAR: usize; +} + +struct A(T); + +impl Foo for A { + const BAR: usize = [5, 6, 7][T::BOO]; +} + +fn foo() -> &'static usize { + & as Foo>::BAR //~ ERROR erroneous constant used +} + +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::() as *const usize as usize); + println!("{:x}", foo::<()>()); + println!("{:x}", foo::()); +} \ No newline at end of file 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..3c613130354 --- /dev/null +++ b/src/test/ui/const-eval/issue-50814-2.stderr @@ -0,0 +1,11 @@ +error[E0080]: erroneous constant used + --> $DIR/issue-50814-2.rs:26:5 + | +LL | & as Foo>::BAR //~ ERROR erroneous constant used + | ^--------------------- + | | + | referenced constant has errors + +error: aborting due to previous error + +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..2af51c48bd4 --- /dev/null +++ b/src/test/ui/const-eval/issue-50814.rs @@ -0,0 +1,32 @@ +// 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 or the MIT license +// , 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); + +impl Unsigned for Sum { + const MAX: u8 = A::MAX + B::MAX; +} + +fn foo(_: T) -> &'static u8 { + &Sum::::MAX //~ ERROR erroneous constant used +} + +fn main() { + foo(0); +} \ No newline at end of file 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..b3e13b43894 --- /dev/null +++ b/src/test/ui/const-eval/issue-50814.stderr @@ -0,0 +1,11 @@ +error[E0080]: erroneous constant used + --> $DIR/issue-50814.rs:27:5 + | +LL | &Sum::::MAX //~ ERROR erroneous constant used + | ^----------------- + | | + | referenced constant has errors + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. From 78d48867da5bf64d41883c67580885943c21f1b9 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Sun, 3 Jun 2018 03:01:06 +0200 Subject: [PATCH 3/8] Properly report transitive errors --- src/librustc/ich/impls_ty.rs | 11 +-- src/librustc/middle/const_val.rs | 21 +++-- src/librustc/mir/interpret/error.rs | 84 +++++++++---------- src/librustc/traits/fulfill.rs | 3 +- src/librustc/ty/structural_impls.rs | 9 +- src/librustc_mir/interpret/const_eval.rs | 3 +- src/librustc_mir/interpret/eval_context.rs | 12 +-- src/librustc_mir/interpret/memory.rs | 16 ++-- src/librustc_mir/monomorphize/collector.rs | 2 +- src/test/compile-fail/const-err-multi.rs | 3 + .../conditional_array_execution.nll.stderr | 31 ++++++- .../const-eval/conditional_array_execution.rs | 2 + .../conditional_array_execution.stderr | 20 ++++- src/test/ui/const-eval/issue-43197.nll.stderr | 49 ++++++++++- src/test/ui/const-eval/issue-43197.rs | 4 + src/test/ui/const-eval/issue-43197.stderr | 38 ++++++++- src/test/ui/const-eval/issue-44578.nll.stderr | 22 ++++- src/test/ui/const-eval/issue-44578.rs | 1 + src/test/ui/const-eval/issue-44578.stderr | 11 ++- src/test/ui/const-eval/issue-50814-2.rs | 1 + src/test/ui/const-eval/issue-50814-2.stderr | 11 ++- src/test/ui/const-eval/issue-50814.rs | 1 + src/test/ui/const-eval/issue-50814.stderr | 11 ++- .../ui/const-len-underflow-separate-spans.rs | 1 + .../const-len-underflow-separate-spans.stderr | 11 ++- 25 files changed, 272 insertions(+), 106 deletions(-) diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index e1e5bc58952..592ada83c85 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -526,19 +526,14 @@ for ::middle::const_val::ErrKind<'gcx> { 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); @@ -609,8 +604,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/middle/const_val.rs b/src/librustc/middle/const_val.rs index d4ec71bc6c4..d2c6bb28948 100644 --- a/src/librustc/middle/const_val.rs +++ b/src/librustc/middle/const_val.rs @@ -9,7 +9,7 @@ // except according to those terms. use hir::def_id::DefId; -use ty::{self, layout}; +use ty; use ty::subst::Substs; use ty::maps::TyCtxtAt; use mir::interpret::ConstValue; @@ -30,27 +30,25 @@ 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>, } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, RustcEncodable, RustcDecodable)] pub enum ErrKind<'tcx> { NonConstPath, - UnimplementedConstVal(&'static str), + CouldNotResolve, IndexOutOfBounds { len: u64, index: u64 }, - LayoutError(layout::LayoutError<'tcx>), - TypeckError, CheckMatchError, Miri(::mir::interpret::EvalError<'tcx>, Vec), } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, RustcEncodable, RustcDecodable)] pub struct FrameInfo { pub span: Span, pub location: String, @@ -87,15 +85,12 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> { match *self.kind { NonConstPath => simple!("non-constant path in constant expression"), - UnimplementedConstVal(what) => - simple!("unimplemented constant expression: {}", what), + CouldNotResolve => simple!("could not resolve"), 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()), - TypeckError => simple!("type-checking failed"), CheckMatchError => simple!("match-checking failed"), Miri(ref err, ref trace) => Backtrace(err, trace), @@ -149,6 +144,10 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> { match miri.kind { ::mir::interpret::EvalErrorKind::TypeckError | ::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), } } diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 1b7c8bdc8a3..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,57 +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, -} - -impl<'tcx> EvalError<'tcx> { - pub fn print_backtrace(&mut self) { - if let Some(ref mut backtrace) = self.backtrace { - use std::fmt::Write; - 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, "\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, "").unwrap(); - } - if let Some(line) = symbol.lineno() { - write!(trace_text, ":{}\n", line).unwrap(); - } else { - write!(trace_text, "\n").unwrap(); - } - } - } - error!("{}", trace_text); - } - } } impl<'tcx> From> 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, "\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, "").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, } } } @@ -158,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, } @@ -274,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/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/structural_impls.rs b/src/librustc/ty/structural_impls.rs index e77ede72143..537efcd9b59 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 { 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, @@ -596,13 +595,9 @@ impl<'a, 'tcx> Lift<'tcx> for const_val::ErrKind<'a> { Some(match *self { NonConstPath => NonConstPath, - UnimplementedConstVal(s) => UnimplementedConstVal(s), + CouldNotResolve => CouldNotResolve, IndexOutOfBounds { len, index } => IndexOutOfBounds { len, index }, - LayoutError(ref e) => { - return tcx.lift(e).map(LayoutError) - } - TypeckError => TypeckError, CheckMatchError => CheckMatchError, Miri(ref e, ref frames) => return tcx.lift(e).map(|e| Miri(e, frames.clone())), diff --git a/src/librustc_mir/interpret/const_eval.rs b/src/librustc_mir/interpret/const_eval.rs index 17df184920c..3fcf1b5c8ed 100644 --- a/src/librustc_mir/interpret/const_eval.rs +++ b/src/librustc_mir/interpret/const_eval.rs @@ -564,8 +564,7 @@ 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| { - err.print_backtrace(); + }).map_err(|err| { let (trace, span) = ecx.generate_stacktrace(None); let err = ErrKind::Miri(err, trace); let err = ConstEvalErr { diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 4c03046f7b1..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}; @@ -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> { 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/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 4f3adaaae27..a8a50c50f59 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -1201,7 +1201,7 @@ fn collect_neighbours<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, 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 { + if let EvalErrorKind::ReferencedConstant(_) = miri.kind { err.report_as_error( tcx.at(mir.promoted[i].span), "erroneous constant used", diff --git a/src/test/compile-fail/const-err-multi.rs b/src/test/compile-fail/const-err-multi.rs index 277a92e8314..4a5e78b381e 100644 --- a/src/test/compile-fail/const-err-multi.rs +++ b/src/test/compile-fail/const-err-multi.rs @@ -17,10 +17,13 @@ pub const A: i8 = -std::i8::MIN; //~| 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/ui/const-eval/conditional_array_execution.nll.stderr b/src/test/ui/const-eval/conditional_array_execution.nll.stderr index a35252c4789..3580950854d 100644 --- a/src/test/ui/const-eval/conditional_array_execution.nll.stderr +++ b/src/test/ui/const-eval/conditional_array_execution.nll.stderr @@ -18,12 +18,32 @@ 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 | @@ -34,12 +54,21 @@ 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]: 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 +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 055224d2731..ac555b25afd 100644 --- a/src/test/ui/const-eval/conditional_array_execution.rs +++ b/src/test/ui/const-eval/conditional_array_execution.rs @@ -19,5 +19,7 @@ const FOO: u32 = [X - Y, Y - X][(X < Y) as usize]; fn main() { println!("{}", FOO); //~^ 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 f396c8f0444..64010c946a7 100644 --- a/src/test/ui/const-eval/conditional_array_execution.stderr +++ b/src/test/ui/const-eval/conditional_array_execution.stderr @@ -18,18 +18,36 @@ 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: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 previous error +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-43197.nll.stderr b/src/test/ui/const-eval/issue-43197.nll.stderr index 416967613f0..3bde12ade90 100644 --- a/src/test/ui/const-eval/issue-43197.nll.stderr +++ b/src/test/ui/const-eval/issue-43197.nll.stderr @@ -32,18 +32,47 @@ 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 | @@ -54,18 +83,36 @@ 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]: 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 3 previous 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 f8d820db747..03aa65eb274 100644 --- a/src/test/ui/const-eval/issue-43197.rs +++ b/src/test/ui/const-eval/issue-43197.rs @@ -28,4 +28,8 @@ fn main() { //~| 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 207523f688f..071d8787307 100644 --- a/src/test/ui/const-eval/issue-43197.stderr +++ b/src/test/ui/const-eval/issue-43197.stderr @@ -32,30 +32,66 @@ 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: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 2 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/const-eval/issue-44578.nll.stderr b/src/test/ui/const-eval/issue-44578.nll.stderr index 49587fa0809..ad4f08966c0 100644 --- a/src/test/ui/const-eval/issue-44578.nll.stderr +++ b/src/test/ui/const-eval/issue-44578.nll.stderr @@ -1,3 +1,14 @@ +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!("{}", 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 | @@ -8,12 +19,21 @@ LL | println!("{}", 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]: 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!("{}", as Foo>::AMT); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + error[E0080]: erroneous constant used --> $DIR/issue-44578.rs:35:20 | LL | println!("{}", as Foo>::AMT); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors -error: aborting due to 2 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/const-eval/issue-44578.rs b/src/test/ui/const-eval/issue-44578.rs index 331de4ab661..59ac4ab311c 100644 --- a/src/test/ui/const-eval/issue-44578.rs +++ b/src/test/ui/const-eval/issue-44578.rs @@ -34,4 +34,5 @@ impl Foo for u16 { fn main() { println!("{}", 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 42d60c604b8..28a723a069e 100644 --- a/src/test/ui/const-eval/issue-44578.stderr +++ b/src/test/ui/const-eval/issue-44578.stderr @@ -1,9 +1,18 @@ +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!("{}", as Foo>::AMT); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + error[E0080]: erroneous constant used --> $DIR/issue-44578.rs:35:20 | LL | println!("{}", as Foo>::AMT); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors -error: aborting due to previous error +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 index a90579296cb..60405da1eb6 100644 --- a/src/test/ui/const-eval/issue-50814-2.rs +++ b/src/test/ui/const-eval/issue-50814-2.rs @@ -24,6 +24,7 @@ impl Foo for A { fn foo() -> &'static usize { & as Foo>::BAR //~ ERROR erroneous constant used +//~| ERROR E0080 } impl C for () { diff --git a/src/test/ui/const-eval/issue-50814-2.stderr b/src/test/ui/const-eval/issue-50814-2.stderr index 3c613130354..3c59cb0e2bc 100644 --- a/src/test/ui/const-eval/issue-50814-2.stderr +++ b/src/test/ui/const-eval/issue-50814-2.stderr @@ -1,3 +1,12 @@ +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 | & as Foo>::BAR //~ ERROR erroneous constant used + | ^^^^^^^^^^^^^^^^^^^^^^ + error[E0080]: erroneous constant used --> $DIR/issue-50814-2.rs:26:5 | @@ -6,6 +15,6 @@ LL | & as Foo>::BAR //~ ERROR erroneous constant used | | | referenced constant has errors -error: aborting due to previous error +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 index 2af51c48bd4..c7140630399 100644 --- a/src/test/ui/const-eval/issue-50814.rs +++ b/src/test/ui/const-eval/issue-50814.rs @@ -25,6 +25,7 @@ impl Unsigned for Sum { fn foo(_: T) -> &'static u8 { &Sum::::MAX //~ ERROR erroneous constant used +//~| ERROR E0080 } fn main() { diff --git a/src/test/ui/const-eval/issue-50814.stderr b/src/test/ui/const-eval/issue-50814.stderr index b3e13b43894..145279ccc03 100644 --- a/src/test/ui/const-eval/issue-50814.stderr +++ b/src/test/ui/const-eval/issue-50814.stderr @@ -1,3 +1,12 @@ +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::::MAX //~ ERROR erroneous constant used + | ^^^^^^^^^^^^^^^^^^ + error[E0080]: erroneous constant used --> $DIR/issue-50814.rs:27:5 | @@ -6,6 +15,6 @@ LL | &Sum::::MAX //~ ERROR erroneous constant used | | | referenced constant has errors -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0080`. 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 09a68a40b3a..630828ef8f5 100644 --- a/src/test/ui/const-len-underflow-separate-spans.stderr +++ b/src/test/ui/const-len-underflow-separate-spans.stderr @@ -12,6 +12,15 @@ error[E0080]: constant evaluation error LL | const LEN: usize = ONE - TWO; | ^^^^^^^^^ attempt to subtract with overflow +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 | @@ -20,6 +29,6 @@ LL | let a: [i8; LEN] = unimplemented!(); | | | 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`. From 13a55e8801c64f0033475ba776dc2c157c54a43d Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Sun, 3 Jun 2018 03:39:26 +0200 Subject: [PATCH 4/8] Satisfy the untiring tidy --- src/test/ui/const-eval/issue-50814-2.rs | 2 +- src/test/ui/const-eval/issue-50814.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/const-eval/issue-50814-2.rs b/src/test/ui/const-eval/issue-50814-2.rs index 60405da1eb6..af627ee5fbe 100644 --- a/src/test/ui/const-eval/issue-50814-2.rs +++ b/src/test/ui/const-eval/issue-50814-2.rs @@ -40,4 +40,4 @@ fn main() { println!("{:x}", foo::() as *const usize as usize); println!("{:x}", foo::<()>()); println!("{:x}", foo::()); -} \ No newline at end of file +} diff --git a/src/test/ui/const-eval/issue-50814.rs b/src/test/ui/const-eval/issue-50814.rs index c7140630399..8f2752453b5 100644 --- a/src/test/ui/const-eval/issue-50814.rs +++ b/src/test/ui/const-eval/issue-50814.rs @@ -30,4 +30,4 @@ fn foo(_: T) -> &'static u8 { fn main() { foo(0); -} \ No newline at end of file +} From 848080dc42a0080fc4dc1d29556aaddbbc3e5bd5 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 5 Jun 2018 19:02:03 +0200 Subject: [PATCH 5/8] Remove unused IndexOutOfBounds variant --- src/librustc/ich/impls_ty.rs | 4 ---- src/librustc/middle/const_val.rs | 7 ------- src/librustc/ty/structural_impls.rs | 2 -- 3 files changed, 13 deletions(-) diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 592ada83c85..fe19196fe06 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -530,10 +530,6 @@ for ::middle::const_val::ErrKind<'gcx> { CheckMatchError => { // nothing to do } - IndexOutOfBounds { len, index } => { - len.hash_stable(hcx, hasher); - index.hash_stable(hcx, hasher); - } Miri(ref err, ref trace) => { err.hash_stable(hcx, hasher); trace.hash_stable(hcx, hasher); diff --git a/src/librustc/middle/const_val.rs b/src/librustc/middle/const_val.rs index d2c6bb28948..3abe405d598 100644 --- a/src/librustc/middle/const_val.rs +++ b/src/librustc/middle/const_val.rs @@ -41,8 +41,6 @@ pub enum ErrKind<'tcx> { NonConstPath, CouldNotResolve, - IndexOutOfBounds { len: u64, index: u64 }, - TypeckError, CheckMatchError, Miri(::mir::interpret::EvalError<'tcx>, Vec), @@ -86,11 +84,6 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> { match *self.kind { NonConstPath => simple!("non-constant path in constant expression"), CouldNotResolve => simple!("could not resolve"), - IndexOutOfBounds { len, index } => { - simple!("index out of bounds: the len is {} but the index is {}", - len, index) - } - TypeckError => simple!("type-checking failed"), CheckMatchError => simple!("match-checking failed"), Miri(ref err, ref trace) => Backtrace(err, trace), diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 537efcd9b59..2055f11f9f8 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -596,8 +596,6 @@ impl<'a, 'tcx> Lift<'tcx> for const_val::ErrKind<'a> { Some(match *self { NonConstPath => NonConstPath, CouldNotResolve => CouldNotResolve, - IndexOutOfBounds { len, index } => IndexOutOfBounds { len, index }, - TypeckError => TypeckError, CheckMatchError => CheckMatchError, Miri(ref e, ref frames) => return tcx.lift(e).map(|e| Miri(e, frames.clone())), From 5950496c92f99d15d85432c0c0eace5fb6b25c02 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 5 Jun 2018 19:06:29 +0200 Subject: [PATCH 6/8] Remove another unused error variant --- src/librustc/ich/impls_ty.rs | 1 - src/librustc/middle/const_val.rs | 2 -- src/librustc/ty/structural_impls.rs | 1 - 3 files changed, 4 deletions(-) diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index fe19196fe06..5e67065d1c1 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -524,7 +524,6 @@ for ::middle::const_val::ErrKind<'gcx> { mem::discriminant(self).hash_stable(hcx, hasher); match *self { - NonConstPath | TypeckError | CouldNotResolve | CheckMatchError => { diff --git a/src/librustc/middle/const_val.rs b/src/librustc/middle/const_val.rs index 3abe405d598..88275b3c18c 100644 --- a/src/librustc/middle/const_val.rs +++ b/src/librustc/middle/const_val.rs @@ -39,7 +39,6 @@ pub struct ConstEvalErr<'tcx> { #[derive(Clone, Debug, RustcEncodable, RustcDecodable)] pub enum ErrKind<'tcx> { - NonConstPath, CouldNotResolve, TypeckError, CheckMatchError, @@ -82,7 +81,6 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> { } match *self.kind { - NonConstPath => simple!("non-constant path in constant expression"), CouldNotResolve => simple!("could not resolve"), TypeckError => simple!("type-checking failed"), CheckMatchError => simple!("match-checking failed"), diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 2055f11f9f8..79a63111850 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -594,7 +594,6 @@ impl<'a, 'tcx> Lift<'tcx> for const_val::ErrKind<'a> { use middle::const_val::ErrKind::*; Some(match *self { - NonConstPath => NonConstPath, CouldNotResolve => CouldNotResolve, TypeckError => TypeckError, CheckMatchError => CheckMatchError, From 8a74be6684a6b0f02c5d4a36cbc19201a9d6f34f Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 5 Jun 2018 19:54:50 +0200 Subject: [PATCH 7/8] Add source information the const propagation of places --- src/librustc_mir/transform/const_prop.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 83b4ea54aab..24382815084 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -233,14 +233,14 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> { } } - fn eval_place(&mut self, place: &Place<'tcx>) -> Option> { + fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option> { 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)) @@ -254,7 +254,8 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> { fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option> { match *op { Operand::Constant(ref c) => self.eval_constant(c, source_info), - Operand::Move(ref place) | Operand::Copy(ref place) => self.eval_place(place), + | Operand::Move(ref place) + | Operand::Copy(ref place) => self.eval_place(place, source_info), } } From 14d08e53710f8be52734ad285d221b224415dc15 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 5 Jun 2018 21:08:43 +0200 Subject: [PATCH 8/8] Rebase fallout --- src/test/ui/const-eval/index_out_of_bounds.rs | 1 + src/test/ui/const-eval/index_out_of_bounds.stderr | 14 +++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) 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`.