提交 5c0d1355 编写于 作者: O Oliver Schneider

Refactor the const eval diagnostic API

上级 4a9c58c6
......@@ -510,6 +510,7 @@ fn hash_stable<W: StableHasherResult>(&self,
impl_stable_hash_for!(struct ::middle::const_val::FrameInfo {
span,
lint_root,
location
});
......
......@@ -655,6 +655,9 @@ fn with_param_env<F>(&mut self, id: ast::NodeId, f: F)
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> {
......
......@@ -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<ast::NodeId>,
}
#[derive(Clone, Debug)]
......@@ -100,64 +103,86 @@ pub fn description(&'a self) -> ConstEvalErrDescription<'a, 'tcx> {
}
pub fn struct_error(&self,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
primary_span: Span,
primary_kind: &str)
-> DiagnosticBuilder<'gcx>
tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
message: &str)
-> Option<DiagnosticBuilder<'tcx>>
{
let mut diag = struct_error(tcx, self.span, "constant evaluation error");
self.note(tcx, primary_span, primary_kind, &mut diag);
diag
self.struct_generic(tcx, message, None, true)
}
pub fn note(&self,
_tcx: TyCtxt<'a, 'gcx, 'tcx>,
primary_span: Span,
primary_kind: &str,
diag: &mut DiagnosticBuilder)
{
match self.description() {
ConstEvalErrDescription::Simple(message) => {
diag.span_label(self.span, message);
}
ConstEvalErrDescription::Backtrace(miri, frames) => {
diag.span_label(self.span, format!("{}", miri));
for frame in frames {
diag.span_label(frame.span, format!("inside call to `{}`", frame.location));
}
}
pub fn report_as_error(&self,
tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
message: &str
) {
let err = self.struct_generic(tcx, message, None, true);
if let Some(mut err) = err {
err.emit();
}
}
if !primary_span.contains(self.span) {
diag.span_note(primary_span,
&format!("for {} here", primary_kind));
pub fn report_as_lint(&self,
tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
message: &str,
lint_root: ast::NodeId,
) {
let lint = self.struct_generic(
tcx,
message,
Some(lint_root),
false,
);
if let Some(mut lint) = lint {
lint.emit();
}
}
pub fn report(&self,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
primary_span: Span,
primary_kind: &str)
{
match *self.kind {
ErrKind::TypeckError | ErrKind::CheckMatchError => return,
ErrKind::Miri(ref miri, _) => {
fn struct_generic(
&self,
tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
message: &str,
lint_root: Option<ast::NodeId>,
as_err: bool,
) -> Option<DiagnosticBuilder<'tcx>> {
let (msg, frames): (_, &[_]) = match *self.kind {
ErrKind::TypeckError | ErrKind::CheckMatchError => return None,
ErrKind::Miri(ref miri, ref frames) => {
match miri.kind {
::mir::interpret::EvalErrorKind::TypeckError |
::mir::interpret::EvalErrorKind::Layout(_) => return,
_ => {},
::mir::interpret::EvalErrorKind::Layout(_) => return None,
_ => (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)
}
......@@ -16,6 +16,42 @@ pub struct EvalError<'tcx> {
pub backtrace: Option<Backtrace>,
}
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, "<unknown>\n").unwrap();
}
write!(trace_text, "\tat ").unwrap();
if let Some(file_path) = symbol.filename() {
write!(trace_text, "{}", file_path.display()).unwrap();
} else {
write!(trace_text, "<unknown_file>").unwrap();
}
if let Some(line) = symbol.lineno() {
write!(trace_text, ":{}\n", line).unwrap();
} else {
write!(trace_text, "\n").unwrap();
}
}
}
error!("{}", trace_text);
}
}
}
impl<'tcx> From<EvalErrorKind<'tcx, u64>> for EvalError<'tcx> {
fn from(kind: EvalErrorKind<'tcx, u64>) -> Self {
let backtrace = match env::var("MIRI_BACKTRACE") {
......
......@@ -827,10 +827,13 @@ pub fn report_selection_error(&self,
}
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 => {
......
......@@ -2075,15 +2075,17 @@ pub fn eval_explicit_discr(
} 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 \
......
......@@ -217,7 +217,10 @@ pub fn simd_shuffle_indices(
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);
......
......@@ -416,7 +416,10 @@ pub fn codegen_operand(&mut self,
// 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.
......
......@@ -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()
}
}
......
......@@ -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
},
};
......
......@@ -141,13 +141,13 @@ fn report_inlining_errors(&self, pat_span: Span) {
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();
}
......
......@@ -695,7 +695,10 @@ fn lower_path(&mut self,
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
},
}
......
......@@ -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
})
}
......
......@@ -15,7 +15,7 @@
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 @@ pub fn generate_stacktrace(&self, explicit_span: Option<Span>) -> (Vec<FrameInfo
let mut last_span = None;
let mut frames = Vec::new();
// skip 1 because the last frame is just the environment of the constant
for &Frame { instance, span, .. } in self.stack().iter().skip(1).rev() {
for &Frame { instance, span, mir, block, stmt, .. } in self.stack().iter().skip(1).rev() {
// make sure we don't emit frames that are duplicates of the previous
if explicit_span == Some(span) {
last_span = Some(span);
......@@ -1644,82 +1644,20 @@ pub fn generate_stacktrace(&self, explicit_span: Option<Span>) -> (Vec<FrameInfo
} else {
instance.to_string()
};
frames.push(FrameInfo { span, location });
}
trace!("generate stacktrace: {:#?}, {:?}", frames, explicit_span);
(frames, self.tcx.span)
}
pub fn report(&self, e: &mut EvalError, as_err: bool, explicit_span: Option<Span>) {
match e.kind {
EvalErrorKind::Layout(_) |
EvalErrorKind::TypeckError => return,
_ => {},
}
if let Some(ref mut backtrace) = e.backtrace {
let mut trace_text = "\n\nAn error occurred in miri:\n".to_string();
backtrace.resolve();
write!(trace_text, "backtrace frames: {}\n", backtrace.frames().len()).unwrap();
'frames: for (i, frame) in backtrace.frames().iter().enumerate() {
if frame.symbols().is_empty() {
write!(trace_text, "{}: no symbols\n", i).unwrap();
}
for symbol in frame.symbols() {
write!(trace_text, "{}: ", i).unwrap();
if let Some(name) = symbol.name() {
write!(trace_text, "{}\n", name).unwrap();
} else {
write!(trace_text, "<unknown>\n").unwrap();
}
write!(trace_text, "\tat ").unwrap();
if let Some(file_path) = symbol.filename() {
write!(trace_text, "{}", file_path.display()).unwrap();
} else {
write!(trace_text, "<unknown_file>").unwrap();
}
if let Some(line) = symbol.lineno() {
write!(trace_text, ":{}\n", line).unwrap();
} else {
write!(trace_text, "\n").unwrap();
}
}
}
error!("{}", trace_text);
}
if let Some(frame) = self.stack().last() {
let block = &frame.mir.basic_blocks()[frame.block];
let span = explicit_span.unwrap_or_else(|| if frame.stmt < block.statements.len() {
block.statements[frame.stmt].source_info.span
} else {
block.terminator().source_info.span
});
trace!("reporting const eval failure at {:?}", span);
let mut err = if as_err {
::rustc::middle::const_val::struct_error(*self.tcx, span, "constant evaluation error")
let block = &mir.basic_blocks()[block];
let source_info = if stmt < block.statements.len() {
block.statements[stmt].source_info
} else {
let node_id = self
.stack()
.iter()
.rev()
.filter_map(|frame| self.tcx.hir.as_local_node_id(frame.instance.def_id()))
.next()
.expect("some part of a failing const eval must be local");
self.tcx.struct_span_lint_node(
::rustc::lint::builtin::CONST_ERR,
node_id,
span,
"constant evaluation error",
)
block.terminator().source_info
};
let (frames, span) = self.generate_stacktrace(explicit_span);
err.span_label(span, e.to_string());
for FrameInfo { span, location } in frames {
err.span_note(span, &format!("inside call to `{}`", location));
}
err.emit();
} else {
self.tcx.sess.err(&e.to_string());
let lint_root = match mir.source_scope_local_data {
mir::ClearCrossCrate::Set(ref ivs) => Some(ivs[source_info.scope].lint_root),
mir::ClearCrossCrate::Clear => None,
};
frames.push(FrameInfo { span, location, lint_root });
}
trace!("generate stacktrace: {:#?}, {:?}", frames, explicit_span);
(frames, self.tcx.span)
}
pub fn sign_extend(&self, value: u128, ty: Ty<'tcx>) -> EvalResult<'tcx, u128> {
......
......@@ -21,7 +21,6 @@
pub use self::const_eval::{
eval_promoted,
mk_borrowck_eval_cx,
eval_body,
CompileTimeEvaluator,
const_value_to_allocation_provider,
const_eval_provider,
......
......@@ -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;
}
}
......
......@@ -17,7 +17,7 @@
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 @@ fn new(
fn use_ecx<F, T>(
&mut self,
span: Span,
source_info: SourceInfo,
f: F
) -> Option<T>
where
F: FnOnce(&mut Self) -> EvalResult<'tcx, T>,
{
self.ecx.tcx.span = span;
self.ecx.tcx.span = source_info.span;
let lint_root = match self.mir.source_scope_local_data {
ClearCrossCrate::Set(ref ivs) => {
use rustc_data_structures::indexed_vec::Idx;
//FIXME(#51314): remove this check
if source_info.scope.index() >= ivs.len() {
return None;
}
ivs[source_info.scope].lint_root
},
ClearCrossCrate::Clear => return None,
};
let r = match f(self) {
Ok(val) => Some(val),
Err(mut err) => {
self.ecx.report(&mut err, false, Some(span));
Err(err) => {
let (frames, span) = self.ecx.generate_stacktrace(None);
let err = ConstEvalErr {
span,
kind: ErrKind::Miri(err, frames).into(),
};
err.report_as_lint(
self.ecx.tcx,
"this expression will panic at runtime",
lint_root,
);
None
},
};
......@@ -139,30 +159,37 @@ fn use_ecx<F, T>(
r
}
fn const_eval(&mut self, cid: GlobalId<'tcx>, span: Span) -> Option<Const<'tcx>> {
fn const_eval(&mut self, cid: GlobalId<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
let value = match self.tcx.const_eval(self.param_env.and(cid)) {
Ok(val) => val,
Err(err) => {
err.report(self.tcx, err.span, "constant propagated");
err.report_as_error(
self.tcx.at(err.span),
"constant evaluation error",
);
return None;
},
};
let val = match value.val {
ConstVal::Value(v) => {
self.use_ecx(span, |this| this.ecx.const_value_to_value(v, value.ty))?
self.use_ecx(source_info, |this| this.ecx.const_value_to_value(v, value.ty))?
},
_ => bug!("eval produced: {:?}", value),
};
let val = (val, value.ty, span);
let val = (val, value.ty, source_info.span);
trace!("evaluated {:?} to {:?}", cid, val);
Some(val)
}
fn eval_constant(&mut self, c: &Constant<'tcx>) -> Option<Const<'tcx>> {
fn eval_constant(
&mut self,
c: &Constant<'tcx>,
source_info: SourceInfo,
) -> Option<Const<'tcx>> {
match c.literal {
Literal::Value { value } => match value.val {
ConstVal::Value(v) => {
let v = self.use_ecx(c.span, |this| {
let v = self.use_ecx(source_info, |this| {
this.ecx.const_value_to_value(v, value.ty)
})?;
Some((v, value.ty, c.span))
......@@ -178,7 +205,7 @@ fn eval_constant(&mut self, c: &Constant<'tcx>) -> Option<Const<'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 @@ fn eval_constant(&mut self, c: &Constant<'tcx>) -> Option<Const<'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 @@ fn eval_place(&mut self, place: &Place<'tcx>) -> Option<Const<'tcx>> {
}
}
fn eval_operand(&mut self, op: &Operand<'tcx>) -> Option<Const<'tcx>> {
fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
match *op {
Operand::Constant(ref c) => self.eval_constant(c),
Operand::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 @@ fn const_prop(
// 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 @@ fn const_prop(
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 @@ fn const_prop(
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 @@ fn const_prop(
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 @@ fn const_prop(
} 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 @@ fn visit_constant(
) {
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 @@ fn visit_terminator_kind(
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 @@ fn visit_terminator_kind(
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,
......
......@@ -4040,7 +4040,10 @@ fn check_expr_kind(&self,
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 {
......
......@@ -16,7 +16,7 @@
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() {
......
......@@ -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
......
......@@ -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
......
......@@ -23,6 +23,7 @@ fn black_box<T>(_: T) {
// Make sure that the two uses get two errors.
const FOO: u8 = [5u8][1];
//~^ ERROR constant evaluation error
//~| ERROR constant evaluation error
//~| index out of bounds: the len is 1 but the index is 1
fn main() {
......
......@@ -16,7 +16,6 @@
//~| 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 @@
//~| 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 @@
//~| 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 @@
//~| 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;
......
......@@ -16,6 +16,6 @@
fn main() {
let a: [i8; ONE - TWO] = unimplemented!();
//~^ ERROR constant evaluation error
//~^ ERROR could not evaluate constant expression
//~| attempt to subtract with overflow
}
......@@ -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
}
......@@ -14,7 +14,6 @@
//~^ ERROR mismatched types
//~| expected tuple, found usize
const ARR: [i32; TUP.0] = [];
//~^ ERROR constant evaluation error
fn main() {
}
......@@ -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() {}
......@@ -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!(),
}
}
......@@ -16,62 +16,62 @@
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
}
......@@ -19,11 +19,11 @@
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"),
}
}
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"),
| ^^^^^^^^^^^
......
......@@ -20,9 +20,9 @@
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() {
......
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
......
......@@ -19,5 +19,5 @@
fn main() {
println!("{}", FOO);
//~^ WARN constant evaluation error
//~^ WARN this expression will panic at runtime
}
......@@ -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);
......
......@@ -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
}
......@@ -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);
......
warning: constant evaluation error
warning: this expression will panic at runtime
--> $DIR/issue-44578.rs:36:20
|
LL | println!("{}", <Bar<u16, u8> 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!("{}", <Bar<u16, u8> as Foo>::AMT); //~ WARN const_err
......
......@@ -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
}
}
......
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
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));
......
......@@ -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
......
......@@ -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
......
......@@ -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
}
......@@ -26,20 +26,16 @@ error[E0019]: constant function contains unimplemented expression type
LL | for i in 0..x {
| ^^^^
error[E0080]: constant evaluation error
--> $DIR/const-fn-error.rs:19:14
error[E0080]: could not evaluate constant expression
--> $DIR/const-fn-error.rs:29:13
|
LL | for i in 0..x {
| ^^^^ calling non-const fn `<I as std::iter::IntoIterator><std::ops::Range<usize>>::into_iter`
| ---- calling non-const fn `<I as std::iter::IntoIterator><std::ops::Range<usize>>::into_iter`
...
LL | let a : [i32; f(X)];
| ---- inside call to `f`
|
note: for constant expression here
--> $DIR/const-fn-error.rs:30:13
|
LL | let a : [i32; f(X)];
| ^^^^^^^^^^^
LL | let a : [i32; f(X)]; //~ ERROR E0080
| ^^^^^^----^
| |
| inside call to `f`
error: aborting due to 5 previous errors
......
......@@ -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
......
......@@ -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
......
......@@ -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(){}
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
......
......@@ -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();
}
......@@ -6,13 +6,6 @@ LL | const l: usize = v.count(); //~ ERROR can't capture dynamic environment
|
= help: use the `|| { ... }` closure form instead
error[E0080]: constant evaluation error
--> $DIR/type-dependent-def-issue-49241.rs:14:18
|
LL | let s: [u32; l] = v.into_iter().collect(); //~ ERROR constant evaluation error
| ^ encountered constants with type errors, stopping evaluation
error: aborting due to 2 previous errors
error: aborting due to previous error
Some errors occurred: E0080, E0434.
For more information about an error, try `rustc --explain E0080`.
For more information about this error, try `rustc --explain E0434`.
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册