Auto merge of #51316 - oli-obk:const_err, r=nikomatsakis

Refactor the const eval diagnostic API

* no longer report "const eval error" for things that have typeck errors
* errors and lints have saner spans and messages
* unified the diagnostic logic (const eval errors were slightly different depending on where they were reported, and there was also code duplication between the different reporters)
* report errors if an erroneous constant is used inside a promoted (fixes most of #50814)
This commit is contained in:
bors 2018-06-06 11:17:15 +00:00
commit 9ac372568b
65 changed files with 884 additions and 464 deletions

View File

@ -510,6 +510,7 @@ impl_stable_hash_for!(struct ::middle::const_val::ConstEvalErr<'tcx> {
impl_stable_hash_for!(struct ::middle::const_val::FrameInfo {
span,
lint_root,
location
});
@ -523,21 +524,11 @@ for ::middle::const_val::ErrKind<'gcx> {
mem::discriminant(self).hash_stable(hcx, hasher);
match *self {
NonConstPath |
TypeckError |
CouldNotResolve |
CheckMatchError => {
// nothing to do
}
UnimplementedConstVal(s) => {
s.hash_stable(hcx, hasher);
}
IndexOutOfBounds { len, index } => {
len.hash_stable(hcx, hasher);
index.hash_stable(hcx, hasher);
}
LayoutError(ref layout_error) => {
layout_error.hash_stable(hcx, hasher);
}
Miri(ref err, ref trace) => {
err.hash_stable(hcx, hasher);
trace.hash_stable(hcx, hasher);
@ -608,8 +599,8 @@ for ::mir::interpret::EvalErrorKind<'gcx, O> {
RemainderByZero |
DivisionByZero |
GeneratorResumedAfterReturn |
GeneratorResumedAfterPanic |
ReferencedConstant => {}
GeneratorResumedAfterPanic => {}
ReferencedConstant(ref err) => err.hash_stable(hcx, hasher),
MachineError(ref err) => err.hash_stable(hcx, hasher),
FunctionPointerTyMismatch(a, b) => {
a.hash_stable(hcx, hasher);

View File

@ -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> {

View File

@ -9,13 +9,15 @@
// except according to those terms.
use hir::def_id::DefId;
use ty::{self, TyCtxt, layout};
use ty;
use ty::subst::Substs;
use ty::maps::TyCtxtAt;
use mir::interpret::ConstValue;
use errors::DiagnosticBuilder;
use graphviz::IntoCow;
use syntax_pos::Span;
use syntax::ast;
use std::borrow::Cow;
use rustc_data_structures::sync::Lrc;
@ -28,30 +30,26 @@ pub enum ConstVal<'tcx> {
Value(ConstValue<'tcx>),
}
#[derive(Clone, Debug)]
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct ConstEvalErr<'tcx> {
pub span: Span,
pub kind: Lrc<ErrKind<'tcx>>,
}
#[derive(Clone, Debug)]
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub enum ErrKind<'tcx> {
NonConstPath,
UnimplementedConstVal(&'static str),
IndexOutOfBounds { len: u64, index: u64 },
LayoutError(layout::LayoutError<'tcx>),
CouldNotResolve,
TypeckError,
CheckMatchError,
Miri(::mir::interpret::EvalError<'tcx>, Vec<FrameInfo>),
}
#[derive(Clone, Debug)]
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct FrameInfo {
pub span: Span,
pub location: String,
pub lint_root: Option<ast::NodeId>,
}
#[derive(Clone, Debug)]
@ -83,16 +81,7 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
}
match *self.kind {
NonConstPath => simple!("non-constant path in constant expression"),
UnimplementedConstVal(what) =>
simple!("unimplemented constant expression: {}", what),
IndexOutOfBounds { len, index } => {
simple!("index out of bounds: the len is {} but the index is {}",
len, index)
}
LayoutError(ref err) => Simple(err.to_string().into_cow()),
CouldNotResolve => simple!("could not resolve"),
TypeckError => simple!("type-checking failed"),
CheckMatchError => simple!("match-checking failed"),
Miri(ref err, ref trace) => Backtrace(err, trace),
@ -100,64 +89,90 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
}
pub fn struct_error(&self,
tcx: TyCtxt<'a, 'gcx, 'tcx>,
primary_span: Span,
primary_kind: &str)
-> DiagnosticBuilder<'gcx>
tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
message: &str)
-> Option<DiagnosticBuilder<'tcx>>
{
let mut diag = struct_error(tcx, self.span, "constant evaluation error");
self.note(tcx, primary_span, primary_kind, &mut diag);
diag
self.struct_generic(tcx, message, None, true)
}
pub fn note(&self,
_tcx: TyCtxt<'a, 'gcx, 'tcx>,
primary_span: Span,
primary_kind: &str,
diag: &mut DiagnosticBuilder)
{
match self.description() {
ConstEvalErrDescription::Simple(message) => {
diag.span_label(self.span, message);
}
ConstEvalErrDescription::Backtrace(miri, frames) => {
diag.span_label(self.span, format!("{}", miri));
for frame in frames {
diag.span_label(frame.span, format!("inside call to `{}`", frame.location));
}
}
}
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<ast::NodeId>,
as_err: bool,
) -> Option<DiagnosticBuilder<'tcx>> {
let (msg, frames): (_, &[_]) = match *self.kind {
ErrKind::TypeckError | ErrKind::CheckMatchError => return None,
ErrKind::Miri(ref miri, ref frames) => {
match miri.kind {
::mir::interpret::EvalErrorKind::TypeckError |
::mir::interpret::EvalErrorKind::Layout(_) => return,
_ => {},
::mir::interpret::EvalErrorKind::Layout(_) => return None,
::mir::interpret::EvalErrorKind::ReferencedConstant(ref inner) => {
inner.struct_generic(tcx, "referenced constant", lint_root, as_err)?.emit();
(miri.to_string(), frames)
},
_ => (miri.to_string(), frames),
}
}
_ => {}
_ => (self.description().into_oneline().to_string(), &[]),
};
trace!("reporting const eval failure at {:?}", self.span);
let mut err = if as_err {
struct_error(tcx, message)
} else {
let node_id = frames
.iter()
.rev()
.filter_map(|frame| frame.lint_root)
.next()
.or(lint_root)
.expect("some part of a failing const eval must be local");
tcx.struct_span_lint_node(
::rustc::lint::builtin::CONST_ERR,
node_id,
tcx.span,
message,
)
};
err.span_label(self.span, msg);
for FrameInfo { span, location, .. } in frames {
err.span_label(*span, format!("inside call to `{}`", location));
}
self.struct_error(tcx, primary_span, primary_kind).emit();
Some(err)
}
}
pub fn struct_error<'a, 'gcx, 'tcx>(
tcx: TyCtxt<'a, 'gcx, 'tcx>,
span: Span,
tcx: TyCtxtAt<'a, 'gcx, 'tcx>,
msg: &str,
) -> DiagnosticBuilder<'gcx> {
struct_span_err!(tcx.sess, span, E0080, "{}", msg)
) -> DiagnosticBuilder<'tcx> {
struct_span_err!(tcx.sess, tcx.span, E0080, "{}", msg)
}

View File

@ -1,6 +1,7 @@
use std::{fmt, env};
use mir;
use middle::const_val::ConstEvalErr;
use ty::{FnSig, Ty, layout};
use ty::layout::{Size, Align};
@ -10,21 +11,50 @@ use super::{
use backtrace::Backtrace;
#[derive(Debug, Clone)]
#[derive(Debug, Clone, RustcEncodable, RustcDecodable)]
pub struct EvalError<'tcx> {
pub kind: EvalErrorKind<'tcx, u64>,
pub backtrace: Option<Backtrace>,
}
impl<'tcx> From<EvalErrorKind<'tcx, u64>> for EvalError<'tcx> {
fn from(kind: EvalErrorKind<'tcx, u64>) -> Self {
let backtrace = match env::var("MIRI_BACKTRACE") {
Ok(ref val) if !val.is_empty() => Some(Backtrace::new_unresolved()),
_ => None
};
match env::var("MIRI_BACKTRACE") {
Ok(ref val) if !val.is_empty() => {
let backtrace = Backtrace::new();
use std::fmt::Write;
let mut trace_text = "\n\nAn error occurred in miri:\n".to_string();
write!(trace_text, "backtrace frames: {}\n", backtrace.frames().len()).unwrap();
'frames: for (i, frame) in backtrace.frames().iter().enumerate() {
if frame.symbols().is_empty() {
write!(trace_text, "{}: no symbols\n", i).unwrap();
}
for symbol in frame.symbols() {
write!(trace_text, "{}: ", i).unwrap();
if let Some(name) = symbol.name() {
write!(trace_text, "{}\n", name).unwrap();
} else {
write!(trace_text, "<unknown>\n").unwrap();
}
write!(trace_text, "\tat ").unwrap();
if let Some(file_path) = symbol.filename() {
write!(trace_text, "{}", file_path.display()).unwrap();
} else {
write!(trace_text, "<unknown_file>").unwrap();
}
if let Some(line) = symbol.lineno() {
write!(trace_text, ":{}\n", line).unwrap();
} else {
write!(trace_text, "\n").unwrap();
}
}
}
error!("{}", trace_text);
},
_ => {},
}
EvalError {
kind,
backtrace,
}
}
}
@ -122,7 +152,7 @@ pub enum EvalErrorKind<'tcx, O> {
TypeckError,
/// Cannot compute this constant because it depends on another one
/// which already produced an error
ReferencedConstant,
ReferencedConstant(ConstEvalErr<'tcx>),
GeneratorResumedAfterReturn,
GeneratorResumedAfterPanic,
}
@ -238,7 +268,7 @@ impl<'tcx, O> EvalErrorKind<'tcx, O> {
"there were unresolved type arguments during trait selection",
TypeckError =>
"encountered constants with type errors, stopping evaluation",
ReferencedConstant =>
ReferencedConstant(_) =>
"referenced constant has errors",
Overflow(mir::BinOp::Add) => "attempt to add with overflow",
Overflow(mir::BinOp::Sub) => "attempt to subtract with overflow",

View File

@ -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 => {

View File

@ -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(),
})))
}
},

View File

@ -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 \

View File

@ -476,7 +476,6 @@ impl<'a, 'tcx> Lift<'tcx> for interpret::EvalError<'a> {
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
Some(interpret::EvalError {
kind: tcx.lift(&self.kind)?,
backtrace: self.backtrace.clone(),
})
}
}
@ -578,7 +577,7 @@ impl<'a, 'tcx, O: Lift<'tcx>> Lift<'tcx> for interpret::EvalErrorKind<'a, O> {
PathNotFound(ref v) => PathNotFound(v.clone()),
UnimplementedTraitSelection => UnimplementedTraitSelection,
TypeckError => TypeckError,
ReferencedConstant => ReferencedConstant,
ReferencedConstant(ref err) => ReferencedConstant(tcx.lift(err)?),
OverflowNeg => OverflowNeg,
Overflow(op) => Overflow(op),
DivisionByZero => DivisionByZero,
@ -595,14 +594,7 @@ impl<'a, 'tcx> Lift<'tcx> for const_val::ErrKind<'a> {
use middle::const_val::ErrKind::*;
Some(match *self {
NonConstPath => NonConstPath,
UnimplementedConstVal(s) => UnimplementedConstVal(s),
IndexOutOfBounds { len, index } => IndexOutOfBounds { len, index },
LayoutError(ref e) => {
return tcx.lift(e).map(LayoutError)
}
CouldNotResolve => CouldNotResolve,
TypeckError => TypeckError,
CheckMatchError => CheckMatchError,
Miri(ref e, ref frames) => return tcx.lift(e).map(|e| Miri(e, frames.clone())),

View File

@ -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);

View File

@ -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.

View File

@ -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()
}
}

View File

@ -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
},
};

View File

@ -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();
}

View File

@ -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
},
}

View File

@ -65,34 +65,12 @@ pub fn eval_promoted<'a, 'mir, 'tcx>(
cid: GlobalId<'tcx>,
mir: &'mir mir::Mir<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> Option<(Value, Scalar, Ty<'tcx>)> {
) -> EvalResult<'tcx, (Value, Scalar, Ty<'tcx>)> {
ecx.with_fresh_body(|ecx| {
let res = eval_body_using_ecx(ecx, cid, Some(mir), param_env);
match res {
Ok(val) => Some(val),
Err(mut err) => {
ecx.report(&mut err, false, None);
None
}
}
eval_body_using_ecx(ecx, cid, Some(mir), param_env)
})
}
pub fn eval_body<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
cid: GlobalId<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> Option<(Value, Scalar, Ty<'tcx>)> {
let (res, ecx) = eval_body_and_ecx(tcx, cid, None, param_env);
match res {
Ok(val) => Some(val),
Err(mut err) => {
ecx.report(&mut err, true, None);
None
}
}
}
pub fn value_to_const_value<'tcx>(
ecx: &EvalContext<'_, '_, 'tcx, CompileTimeEvaluator>,
val: Value,
@ -124,9 +102,17 @@ pub fn value_to_const_value<'tcx>(
})();
match val {
Ok(val) => ty::Const::from_const_value(ecx.tcx.tcx, val, ty),
Err(mut err) => {
ecx.report(&mut err, true, None);
bug!("miri error occured when converting Value to ConstValue")
Err(err) => {
let (frames, span) = ecx.generate_stacktrace(None);
let err = ConstEvalErr {
span,
kind: ErrKind::Miri(err, frames).into(),
};
err.report_as_error(
ecx.tcx,
"failed to convert Value to ConstValue, this is a bug",
);
span_bug!(span, "miri error occured when converting Value to ConstValue")
}
}
}
@ -578,16 +564,17 @@ pub fn const_eval_provider<'a, 'tcx>(
val = ecx.try_read_by_ref(val, miri_ty)?;
}
Ok(value_to_const_value(&ecx, val, miri_ty))
}).map_err(|mut err| {
if tcx.is_static(def_id).is_some() {
ecx.report(&mut err, true, None);
}
}).map_err(|err| {
let (trace, span) = ecx.generate_stacktrace(None);
let err = ErrKind::Miri(err, trace);
ConstEvalErr {
let err = ConstEvalErr {
kind: err.into(),
span,
};
if tcx.is_static(def_id).is_some() {
err.report_as_error(ecx.tcx, "could not evaluate static initializer");
}
err
})
}

View File

@ -3,7 +3,7 @@ use std::fmt::Write;
use rustc::hir::def_id::DefId;
use rustc::hir::def::Def;
use rustc::hir::map::definitions::DefPathData;
use rustc::middle::const_val::{ConstVal, ErrKind};
use rustc::middle::const_val::ConstVal;
use rustc::mir;
use rustc::ty::layout::{self, Size, Align, HasDataLayout, IntegerExt, LayoutOf, TyLayout};
use rustc::ty::subst::{Subst, Substs};
@ -15,7 +15,7 @@ use syntax::codemap::{self, Span};
use syntax::ast::Mutability;
use rustc::mir::interpret::{
GlobalId, Value, Scalar,
EvalError, EvalResult, EvalErrorKind, Pointer, ConstValue,
EvalResult, EvalErrorKind, Pointer, ConstValue,
};
use std::mem;
@ -1056,15 +1056,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
} else {
self.param_env
};
self.tcx.const_eval(param_env.and(gid)).map_err(|err| match *err.kind {
ErrKind::Miri(ref err, _) => match err.kind {
EvalErrorKind::TypeckError |
EvalErrorKind::Layout(_) => EvalErrorKind::TypeckError.into(),
_ => EvalErrorKind::ReferencedConstant.into(),
},
ErrKind::TypeckError => EvalErrorKind::TypeckError.into(),
ref other => bug!("const eval returned {:?}", other),
})
self.tcx.const_eval(param_env.and(gid)).map_err(|err| EvalErrorKind::ReferencedConstant(err).into())
}
pub fn force_allocation(&mut self, place: Place) -> EvalResult<'tcx, Place> {
@ -1626,7 +1618,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
let mut last_span = None;
let mut frames = Vec::new();
// skip 1 because the last frame is just the environment of the constant
for &Frame { instance, span, .. } in self.stack().iter().skip(1).rev() {
for &Frame { instance, span, mir, block, stmt, .. } in self.stack().iter().skip(1).rev() {
// make sure we don't emit frames that are duplicates of the previous
if explicit_span == Some(span) {
last_span = Some(span);
@ -1644,84 +1636,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<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")
} 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)
}

View File

@ -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,

View File

@ -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,

View File

@ -388,7 +388,10 @@ fn collect_items_rec<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
Ok(val) => collect_const(tcx, val, instance.substs, &mut neighbors),
Err(err) => {
let span = tcx.def_span(def_id);
err.report(tcx, span, "static");
err.report_as_error(
tcx.at(span),
"could not evaluate static initializer",
);
}
}
}
@ -1187,13 +1190,25 @@ fn collect_neighbours<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
let param_env = ty::ParamEnv::reveal_all();
for i in 0..mir.promoted.len() {
use rustc_data_structures::indexed_vec::Idx;
let i = Promoted::new(i);
let cid = GlobalId {
instance,
promoted: Some(Promoted::new(i)),
promoted: Some(i),
};
match tcx.const_eval(param_env.and(cid)) {
Ok(val) => collect_const(tcx, val, instance.substs, output),
Err(_) => {},
Err(err) => {
use rustc::middle::const_val::ErrKind;
use rustc::mir::interpret::EvalErrorKind;
if let ErrKind::Miri(ref miri, ..) = *err.kind {
if let EvalErrorKind::ReferencedConstant(_) = miri.kind {
err.report_as_error(
tcx.at(mir.promoted[i].span),
"erroneous constant used",
);
}
}
},
}
}
}
@ -1236,7 +1251,10 @@ fn collect_const<'a, 'tcx>(
Ok(val) => val.val,
Err(err) => {
let span = tcx.def_span(def_id);
err.report(tcx, span, "constant");
err.report_as_error(
tcx.at(span),
"constant evaluation error",
);
return;
}
}

View File

@ -17,7 +17,7 @@ use rustc::mir::{Constant, Literal, Location, Place, Mir, Operand, Rvalue, Local
use rustc::mir::{NullOp, StatementKind, Statement, BasicBlock, LocalKind};
use rustc::mir::{TerminatorKind, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem};
use rustc::mir::visit::{Visitor, PlaceContext};
use rustc::middle::const_val::ConstVal;
use rustc::middle::const_val::{ConstVal, ConstEvalErr, ErrKind};
use rustc::ty::{TyCtxt, self, Instance};
use rustc::mir::interpret::{Value, Scalar, GlobalId, EvalResult};
use interpret::EvalContext;
@ -121,17 +121,37 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
fn use_ecx<F, T>(
&mut self,
span: Span,
source_info: SourceInfo,
f: F
) -> Option<T>
where
F: FnOnce(&mut Self) -> EvalResult<'tcx, T>,
{
self.ecx.tcx.span = span;
self.ecx.tcx.span = source_info.span;
let lint_root = match self.mir.source_scope_local_data {
ClearCrossCrate::Set(ref ivs) => {
use rustc_data_structures::indexed_vec::Idx;
//FIXME(#51314): remove this check
if source_info.scope.index() >= ivs.len() {
return None;
}
ivs[source_info.scope].lint_root
},
ClearCrossCrate::Clear => return None,
};
let r = match f(self) {
Ok(val) => Some(val),
Err(mut err) => {
self.ecx.report(&mut err, false, Some(span));
Err(err) => {
let (frames, span) = self.ecx.generate_stacktrace(None);
let err = ConstEvalErr {
span,
kind: ErrKind::Miri(err, frames).into(),
};
err.report_as_lint(
self.ecx.tcx,
"this expression will panic at runtime",
lint_root,
);
None
},
};
@ -139,30 +159,37 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
r
}
fn const_eval(&mut self, cid: GlobalId<'tcx>, span: Span) -> Option<Const<'tcx>> {
fn const_eval(&mut self, cid: GlobalId<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
let value = match self.tcx.const_eval(self.param_env.and(cid)) {
Ok(val) => val,
Err(err) => {
err.report(self.tcx, err.span, "constant propagated");
err.report_as_error(
self.tcx.at(err.span),
"constant evaluation error",
);
return None;
},
};
let val = match value.val {
ConstVal::Value(v) => {
self.use_ecx(span, |this| this.ecx.const_value_to_value(v, value.ty))?
self.use_ecx(source_info, |this| this.ecx.const_value_to_value(v, value.ty))?
},
_ => bug!("eval produced: {:?}", value),
};
let val = (val, value.ty, span);
let val = (val, value.ty, source_info.span);
trace!("evaluated {:?} to {:?}", cid, val);
Some(val)
}
fn eval_constant(&mut self, c: &Constant<'tcx>) -> Option<Const<'tcx>> {
fn eval_constant(
&mut self,
c: &Constant<'tcx>,
source_info: SourceInfo,
) -> Option<Const<'tcx>> {
match c.literal {
Literal::Value { value } => match value.val {
ConstVal::Value(v) => {
let v = self.use_ecx(c.span, |this| {
let v = self.use_ecx(source_info, |this| {
this.ecx.const_value_to_value(v, value.ty)
})?;
Some((v, value.ty, c.span))
@ -178,7 +205,7 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
instance,
promoted: None,
};
self.const_eval(cid, c.span)
self.const_eval(cid, source_info)
},
},
// evaluate the promoted and replace the constant with the evaluated result
@ -196,10 +223,9 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
};
// cannot use `const_eval` here, because that would require having the MIR
// for the current function available, but we're producing said MIR right now
let span = self.mir.span;
let (value, _, ty) = self.use_ecx(span, |this| {
Ok(eval_promoted(&mut this.ecx, cid, this.mir, this.param_env))
})??;
let (value, _, ty) = self.use_ecx(source_info, |this| {
eval_promoted(&mut this.ecx, cid, this.mir, this.param_env)
})?;
let val = (value, ty, c.span);
trace!("evaluated {:?} to {:?}", c, val);
Some(val)
@ -207,14 +233,14 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
}
}
fn eval_place(&mut self, place: &Place<'tcx>) -> Option<Const<'tcx>> {
fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
match *place {
Place::Local(loc) => self.places[loc].clone(),
Place::Projection(ref proj) => match proj.elem {
ProjectionElem::Field(field, _) => {
trace!("field proj on {:?}", proj.base);
let (base, ty, span) = self.eval_place(&proj.base)?;
let valty = self.use_ecx(span, |this| {
let (base, ty, span) = self.eval_place(&proj.base, source_info)?;
let valty = self.use_ecx(source_info, |this| {
this.ecx.read_field(base, None, field, ty)
})?;
Some((valty.value, valty.ty, span))
@ -225,10 +251,11 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
}
}
fn eval_operand(&mut self, op: &Operand<'tcx>) -> Option<Const<'tcx>> {
fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
match *op {
Operand::Constant(ref c) => self.eval_constant(c),
Operand::Move(ref place) | Operand::Copy(ref place) => self.eval_place(place),
Operand::Constant(ref c) => self.eval_constant(c, source_info),
| Operand::Move(ref place)
| Operand::Copy(ref place) => self.eval_place(place, source_info),
}
}
@ -243,10 +270,10 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
// This branch exists for the sanity type check
Rvalue::Use(Operand::Constant(ref c)) => {
assert_eq!(c.ty, place_ty);
self.eval_constant(c)
self.eval_constant(c, source_info)
},
Rvalue::Use(ref op) => {
self.eval_operand(op)
self.eval_operand(op, source_info)
},
Rvalue::Repeat(..) |
Rvalue::Ref(..) |
@ -279,17 +306,17 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
return None;
}
let val = self.eval_operand(arg)?;
let prim = self.use_ecx(span, |this| {
let val = self.eval_operand(arg, source_info)?;
let prim = self.use_ecx(source_info, |this| {
this.ecx.value_to_scalar(ValTy { value: val.0, ty: val.1 })
})?;
let val = self.use_ecx(span, |this| this.ecx.unary_op(op, prim, val.1))?;
let val = self.use_ecx(source_info, |this| this.ecx.unary_op(op, prim, val.1))?;
Some((Value::Scalar(val), place_ty, span))
}
Rvalue::CheckedBinaryOp(op, ref left, ref right) |
Rvalue::BinaryOp(op, ref left, ref right) => {
trace!("rvalue binop {:?} for {:?} and {:?}", op, left, right);
let right = self.eval_operand(right)?;
let right = self.eval_operand(right, source_info)?;
let def_id = if self.tcx.is_closure(self.source.def_id) {
self.tcx.closure_base_def_id(self.source.def_id)
} else {
@ -301,7 +328,7 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
return None;
}
let r = self.use_ecx(span, |this| {
let r = self.use_ecx(source_info, |this| {
this.ecx.value_to_scalar(ValTy { value: right.0, ty: right.1 })
})?;
if op == BinOp::Shr || op == BinOp::Shl {
@ -332,12 +359,12 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
return None;
}
}
let left = self.eval_operand(left)?;
let l = self.use_ecx(span, |this| {
let left = self.eval_operand(left, source_info)?;
let l = self.use_ecx(source_info, |this| {
this.ecx.value_to_scalar(ValTy { value: left.0, ty: left.1 })
})?;
trace!("const evaluating {:?} for {:?} and {:?}", op, left, right);
let (val, overflow) = self.use_ecx(span, |this| {
let (val, overflow) = self.use_ecx(source_info, |this| {
this.ecx.binary_op(op, l, left.1, r, right.1)
})?;
let val = if let Rvalue::CheckedBinaryOp(..) = *rvalue {
@ -348,11 +375,8 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
} else {
if overflow {
use rustc::mir::interpret::EvalErrorKind;
let mut err = EvalErrorKind::Overflow(op).into();
self.use_ecx(span, |this| {
this.ecx.report(&mut err, false, Some(span));
Ok(())
});
let err = EvalErrorKind::Overflow(op).into();
let _: Option<()> = self.use_ecx(source_info, |_| Err(err));
return None;
}
Value::Scalar(val)
@ -431,7 +455,8 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
) {
trace!("visit_constant: {:?}", constant);
self.super_constant(constant, location);
self.eval_constant(constant);
let source_info = *self.mir.source_info(location);
self.eval_constant(constant, source_info);
}
fn visit_statement(
@ -466,8 +491,9 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
location: Location,
) {
self.super_terminator_kind(block, kind, location);
let source_info = *self.mir.source_info(location);
if let TerminatorKind::Assert { expected, msg, cond, .. } = kind {
if let Some(value) = self.eval_operand(cond) {
if let Some(value) = self.eval_operand(cond, source_info) {
trace!("assertion on {:?} should be {:?}", value, expected);
if Value::Scalar(Scalar::from_bool(*expected)) != value.0 {
// poison all places this operand references so that further code
@ -502,13 +528,15 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
DivisionByZero |
RemainderByZero => msg.description().to_owned(),
BoundsCheck { ref len, ref index } => {
let len = self.eval_operand(len).expect("len must be const");
let len = self
.eval_operand(len, source_info)
.expect("len must be const");
let len = match len.0 {
Value::Scalar(Scalar::Bits { bits, ..}) => bits,
_ => bug!("const len not primitive: {:?}", len),
};
let index = self
.eval_operand(index)
.eval_operand(index, source_info)
.expect("index must be const");
let index = match index.0 {
Value::Scalar(Scalar::Bits { bits, .. }) => bits,

View File

@ -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 {

View File

@ -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() {

View File

@ -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

View File

@ -13,14 +13,17 @@
pub const A: i8 = -std::i8::MIN;
//~^ ERROR E0080
//~| ERROR attempt to negate with overflow
//~| ERROR constant evaluation error
//~| ERROR this expression will panic at runtime
//~| ERROR this constant cannot be used
pub const B: i8 = A;
//~^ ERROR const_err
//~| ERROR const_err
pub const C: u8 = A as u8;
//~^ ERROR const_err
//~| ERROR const_err
pub const D: i8 = 50 - A;
//~^ ERROR const_err
//~| ERROR const_err
fn main() {
let _ = (A, B, C, D);

View File

@ -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() {

View File

@ -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;

View File

@ -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
}

View File

@ -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
}

View File

@ -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() {
}

View File

@ -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() {}

View File

@ -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!(),
}
}

View File

@ -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
}

View File

@ -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"),
}
}

View File

@ -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"),
| ^^^^^^^^^^^

View File

@ -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() {

View File

@ -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

View File

@ -0,0 +1,74 @@
warning: attempt to subtract with overflow
--> $DIR/conditional_array_execution.rs:15:19
|
LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
| ^^^^^
|
note: lint level defined here
--> $DIR/conditional_array_execution.rs:11:9
|
LL | #![warn(const_err)]
| ^^^^^^^^^
warning: this constant cannot be used
--> $DIR/conditional_array_execution.rs:15:1
|
LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
| ^^^^^^^^^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| attempt to subtract with overflow
warning: referenced constant
--> $DIR/conditional_array_execution.rs:20:20
|
LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
| ----- attempt to subtract with overflow
...
LL | println!("{}", FOO);
| ^^^
warning: this expression will panic at runtime
--> $DIR/conditional_array_execution.rs:20:20
|
LL | println!("{}", FOO);
| ^^^ referenced constant has errors
error[E0080]: referenced constant
--> $DIR/conditional_array_execution.rs:20:5
|
LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
| ----- attempt to subtract with overflow
...
LL | println!("{}", FOO);
| ^^^^^^^^^^^^^^^^^^^^
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error[E0080]: erroneous constant used
--> $DIR/conditional_array_execution.rs:20:5
|
LL | println!("{}", FOO);
| ^^^^^^^^^^^^^^^---^^
| |
| referenced constant has errors
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error[E0080]: referenced constant
--> $DIR/conditional_array_execution.rs:20:20
|
LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
| ----- attempt to subtract with overflow
...
LL | println!("{}", FOO);
| ^^^
error[E0080]: erroneous constant used
--> $DIR/conditional_array_execution.rs:20:20
|
LL | println!("{}", FOO);
| ^^^ referenced constant has errors
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0080`.

View File

@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// compile-pass
#![warn(const_err)]
const X: u32 = 5;
@ -19,5 +18,8 @@ const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
fn main() {
println!("{}", FOO);
//~^ WARN constant evaluation error
//~^ WARN this expression will panic at runtime
//~| WARN referenced constant
//~| ERROR erroneous constant used
//~| E0080
}

View File

@ -1,24 +1,53 @@
warning: attempt to subtract with overflow
--> $DIR/conditional_array_execution.rs:16:19
--> $DIR/conditional_array_execution.rs:15:19
|
LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
| ^^^^^
|
note: lint level defined here
--> $DIR/conditional_array_execution.rs:12:9
--> $DIR/conditional_array_execution.rs:11:9
|
LL | #![warn(const_err)]
| ^^^^^^^^^
warning: this constant cannot be used
--> $DIR/conditional_array_execution.rs:16:1
--> $DIR/conditional_array_execution.rs:15:1
|
LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
| ^^^^^^^^^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| attempt to subtract with overflow
warning: constant evaluation error
--> $DIR/conditional_array_execution.rs:21:20
warning: referenced constant
--> $DIR/conditional_array_execution.rs:20:20
|
LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
| ----- attempt to subtract with overflow
...
LL | println!("{}", FOO);
| ^^^
warning: this expression will panic at runtime
--> $DIR/conditional_array_execution.rs:20:20
|
LL | println!("{}", FOO);
| ^^^ referenced constant has errors
error[E0080]: referenced constant
--> $DIR/conditional_array_execution.rs:20:20
|
LL | const FOO: u32 = [X - Y, Y - X][(X < Y) as usize];
| ----- attempt to subtract with overflow
...
LL | println!("{}", FOO);
| ^^^
error[E0080]: erroneous constant used
--> $DIR/conditional_array_execution.rs:20:20
|
LL | println!("{}", FOO);
| ^^^ referenced constant has errors
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0080`.

View File

@ -10,6 +10,7 @@
static FOO: i32 = [][0];
//~^ ERROR E0080
//~| ERROR E0080
fn main() {
let array = [std::env::args().len()];

View File

@ -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`.

View File

@ -0,0 +1,118 @@
warning: attempt to subtract with overflow
--> $DIR/issue-43197.rs:20:20
|
LL | const X: u32 = 0-1;
| ^^^
|
note: lint level defined here
--> $DIR/issue-43197.rs:11:9
|
LL | #![warn(const_err)]
| ^^^^^^^^^
warning: this constant cannot be used
--> $DIR/issue-43197.rs:20:5
|
LL | const X: u32 = 0-1;
| ^^^^^^^^^^^^^^^---^
| |
| attempt to subtract with overflow
warning: attempt to subtract with overflow
--> $DIR/issue-43197.rs:23:24
|
LL | const Y: u32 = foo(0-1);
| ^^^
warning: this constant cannot be used
--> $DIR/issue-43197.rs:23:5
|
LL | const Y: u32 = foo(0-1);
| ^^^^^^^^^^^^^^^^^^^---^^
| |
| attempt to subtract with overflow
warning: referenced constant
--> $DIR/issue-43197.rs:26:23
|
LL | const X: u32 = 0-1;
| --- attempt to subtract with overflow
...
LL | println!("{} {}", X, Y);
| ^
warning: this expression will panic at runtime
--> $DIR/issue-43197.rs:26:23
|
LL | println!("{} {}", X, Y);
| ^ referenced constant has errors
warning: referenced constant
--> $DIR/issue-43197.rs:26:26
|
LL | const Y: u32 = foo(0-1);
| --- attempt to subtract with overflow
...
LL | println!("{} {}", X, Y);
| ^
warning: this expression will panic at runtime
--> $DIR/issue-43197.rs:26:26
|
LL | println!("{} {}", X, Y);
| ^ referenced constant has errors
error[E0080]: referenced constant
--> $DIR/issue-43197.rs:26:5
|
LL | const X: u32 = 0-1;
| --- attempt to subtract with overflow
...
LL | println!("{} {}", X, Y);
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error[E0080]: erroneous constant used
--> $DIR/issue-43197.rs:26:5
|
LL | println!("{} {}", X, Y);
| ^^^^^^^^^^^^^^^^^^-^^^^^
| |
| referenced constant has errors
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error[E0080]: referenced constant
--> $DIR/issue-43197.rs:26:26
|
LL | const Y: u32 = foo(0-1);
| --- attempt to subtract with overflow
...
LL | println!("{} {}", X, Y);
| ^
error[E0080]: erroneous constant used
--> $DIR/issue-43197.rs:26:26
|
LL | println!("{} {}", X, Y);
| ^ referenced constant has errors
error[E0080]: referenced constant
--> $DIR/issue-43197.rs:26:23
|
LL | const X: u32 = 0-1;
| --- attempt to subtract with overflow
...
LL | println!("{} {}", X, Y);
| ^
error[E0080]: erroneous constant used
--> $DIR/issue-43197.rs:26:23
|
LL | println!("{} {}", X, Y);
| ^ referenced constant has errors
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0080`.

View File

@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// compile-pass
#![warn(const_err)]
#![feature(const_fn)]
@ -25,6 +24,12 @@ fn main() {
//~^ WARN attempt to subtract with overflow
//~| WARN this constant cannot be used
println!("{} {}", X, Y);
//~^ WARN constant evaluation error
//~| WARN constant evaluation error
//~^ WARN this expression will panic at runtime
//~| WARN this expression will panic at runtime
//~| ERROR erroneous constant used
//~| ERROR erroneous constant used
//~| ERROR E0080
//~| ERROR E0080
//~| WARN referenced constant
//~| WARN referenced constant
}

View File

@ -1,42 +1,97 @@
warning: attempt to subtract with overflow
--> $DIR/issue-43197.rs:21:20
--> $DIR/issue-43197.rs:20:20
|
LL | const X: u32 = 0-1;
| ^^^
|
note: lint level defined here
--> $DIR/issue-43197.rs:12:9
--> $DIR/issue-43197.rs:11:9
|
LL | #![warn(const_err)]
| ^^^^^^^^^
warning: this constant cannot be used
--> $DIR/issue-43197.rs:21:5
--> $DIR/issue-43197.rs:20:5
|
LL | const X: u32 = 0-1;
| ^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
| ^^^^^^^^^^^^^^^---^
| |
| attempt to subtract with overflow
warning: attempt to subtract with overflow
--> $DIR/issue-43197.rs:24:24
--> $DIR/issue-43197.rs:23:24
|
LL | const Y: u32 = foo(0-1);
| ^^^
warning: this constant cannot be used
--> $DIR/issue-43197.rs:24:5
--> $DIR/issue-43197.rs:23:5
|
LL | const Y: u32 = foo(0-1);
| ^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow
| ^^^^^^^^^^^^^^^^^^^---^^
| |
| attempt to subtract with overflow
warning: constant evaluation error
--> $DIR/issue-43197.rs:27:23
warning: referenced constant
--> $DIR/issue-43197.rs:26:23
|
LL | const X: u32 = 0-1;
| --- attempt to subtract with overflow
...
LL | println!("{} {}", X, Y);
| ^
warning: this expression will panic at runtime
--> $DIR/issue-43197.rs:26:23
|
LL | println!("{} {}", X, Y);
| ^ referenced constant has errors
warning: constant evaluation error
--> $DIR/issue-43197.rs:27:26
warning: referenced constant
--> $DIR/issue-43197.rs:26:26
|
LL | const Y: u32 = foo(0-1);
| --- attempt to subtract with overflow
...
LL | println!("{} {}", X, Y);
| ^
warning: this expression will panic at runtime
--> $DIR/issue-43197.rs:26:26
|
LL | println!("{} {}", X, Y);
| ^ referenced constant has errors
error[E0080]: referenced constant
--> $DIR/issue-43197.rs:26:26
|
LL | const Y: u32 = foo(0-1);
| --- attempt to subtract with overflow
...
LL | println!("{} {}", X, Y);
| ^
error[E0080]: erroneous constant used
--> $DIR/issue-43197.rs:26:26
|
LL | println!("{} {}", X, Y);
| ^ referenced constant has errors
error[E0080]: referenced constant
--> $DIR/issue-43197.rs:26:23
|
LL | const X: u32 = 0-1;
| --- attempt to subtract with overflow
...
LL | println!("{} {}", X, Y);
| ^
error[E0080]: erroneous constant used
--> $DIR/issue-43197.rs:26:23
|
LL | println!("{} {}", X, Y);
| ^ referenced constant has errors
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0080`.

View File

@ -0,0 +1,39 @@
error[E0080]: referenced constant
--> $DIR/issue-44578.rs:35:5
|
LL | const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize];
| ------------------------------------ index out of bounds: the len is 1 but the index is 1
...
LL | println!("{}", <Bar<u16, u8> as Foo>::AMT);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error[E0080]: erroneous constant used
--> $DIR/issue-44578.rs:35:5
|
LL | println!("{}", <Bar<u16, u8> as Foo>::AMT);
| ^^^^^^^^^^^^^^^--------------------------^^
| |
| referenced constant has errors
|
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
error[E0080]: referenced constant
--> $DIR/issue-44578.rs:35:20
|
LL | const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize];
| ------------------------------------ index out of bounds: the len is 1 but the index is 1
...
LL | println!("{}", <Bar<u16, u8> as Foo>::AMT);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: erroneous constant used
--> $DIR/issue-44578.rs:35:20
|
LL | println!("{}", <Bar<u16, u8> as Foo>::AMT);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0080`.

View File

@ -8,8 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// compile-pass
#![warn(const_err)]
#![allow(const_err)]
trait Foo {
const AMT: usize;
@ -33,6 +32,7 @@ impl Foo for u16 {
}
fn main() {
println!("{}", <Bar<u16, u8> as Foo>::AMT); //~ WARN const_err
//~^ WARN const_err
println!("{}", <Bar<u16, u8> as Foo>::AMT);
//~^ ERROR erroneous constant used
//~| ERROR E0080
}

View File

@ -1,18 +1,18 @@
warning: constant evaluation error
--> $DIR/issue-44578.rs:36:20
error[E0080]: referenced constant
--> $DIR/issue-44578.rs:35:20
|
LL | println!("{}", <Bar<u16, u8> as Foo>::AMT); //~ WARN const_err
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
|
note: lint level defined here
--> $DIR/issue-44578.rs:12:9
|
LL | #![warn(const_err)]
| ^^^^^^^^^
LL | const AMT: usize = [A::AMT][(A::AMT > B::AMT) as usize];
| ------------------------------------ index out of bounds: the len is 1 but the index is 1
...
LL | println!("{}", <Bar<u16, u8> as Foo>::AMT);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: constant evaluation error
--> $DIR/issue-44578.rs:36:20
error[E0080]: erroneous constant used
--> $DIR/issue-44578.rs:35:20
|
LL | println!("{}", <Bar<u16, u8> as Foo>::AMT); //~ WARN const_err
LL | println!("{}", <Bar<u16, u8> as Foo>::AMT);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0080`.

View File

@ -0,0 +1,43 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
trait C {
const BOO: usize;
}
trait Foo<T> {
const BAR: usize;
}
struct A<T>(T);
impl<T: C> Foo<T> for A<T> {
const BAR: usize = [5, 6, 7][T::BOO];
}
fn foo<T: C>() -> &'static usize {
&<A<T> as Foo<T>>::BAR //~ ERROR erroneous constant used
//~| ERROR E0080
}
impl C for () {
const BOO: usize = 42;
}
impl C for u32 {
const BOO: usize = 1;
}
fn main() {
println!("{:x}", foo::<()>() as *const usize as usize);
println!("{:x}", foo::<u32>() as *const usize as usize);
println!("{:x}", foo::<()>());
println!("{:x}", foo::<u32>());
}

View File

@ -0,0 +1,20 @@
error[E0080]: referenced constant
--> $DIR/issue-50814-2.rs:26:5
|
LL | const BAR: usize = [5, 6, 7][T::BOO];
| ----------------- index out of bounds: the len is 3 but the index is 42
...
LL | &<A<T> as Foo<T>>::BAR //~ ERROR erroneous constant used
| ^^^^^^^^^^^^^^^^^^^^^^
error[E0080]: erroneous constant used
--> $DIR/issue-50814-2.rs:26:5
|
LL | &<A<T> as Foo<T>>::BAR //~ ERROR erroneous constant used
| ^---------------------
| |
| referenced constant has errors
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0080`.

View File

@ -0,0 +1,33 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
trait Unsigned {
const MAX: u8;
}
struct U8(u8);
impl Unsigned for U8 {
const MAX: u8 = 0xff;
}
struct Sum<A,B>(A,B);
impl<A: Unsigned, B: Unsigned> Unsigned for Sum<A,B> {
const MAX: u8 = A::MAX + B::MAX;
}
fn foo<T>(_: T) -> &'static u8 {
&Sum::<U8,U8>::MAX //~ ERROR erroneous constant used
//~| ERROR E0080
}
fn main() {
foo(0);
}

View File

@ -0,0 +1,20 @@
error[E0080]: referenced constant
--> $DIR/issue-50814.rs:27:5
|
LL | const MAX: u8 = A::MAX + B::MAX;
| --------------- attempt to add with overflow
...
LL | &Sum::<U8,U8>::MAX //~ ERROR erroneous constant used
| ^^^^^^^^^^^^^^^^^^
error[E0080]: erroneous constant used
--> $DIR/issue-50814.rs:27:5
|
LL | &Sum::<U8,U8>::MAX //~ ERROR erroneous constant used
| ^-----------------
| |
| referenced constant has errors
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0080`.

View File

@ -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
}
}

View File

@ -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

View File

@ -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));

View File

@ -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

View File

@ -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

View File

@ -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
}

View File

@ -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

View File

@ -21,4 +21,5 @@ const LEN: usize = ONE - TWO;
fn main() {
let a: [i8; LEN] = unimplemented!();
//~^ ERROR E0080
//~| ERROR E0080
}

View File

@ -12,12 +12,23 @@ error[E0080]: constant evaluation error
LL | const LEN: usize = ONE - TWO;
| ^^^^^^^^^ attempt to subtract with overflow
error[E0080]: constant evaluation error
--> $DIR/const-len-underflow-separate-spans.rs:22:17
error[E0080]: referenced constant
--> $DIR/const-len-underflow-separate-spans.rs:22:12
|
LL | const LEN: usize = ONE - TWO;
| --------- attempt to subtract with overflow
...
LL | let a: [i8; LEN] = unimplemented!();
| ^^^^^^^^^
error[E0080]: could not evaluate constant expression
--> $DIR/const-len-underflow-separate-spans.rs:22:12
|
LL | let a: [i8; LEN] = unimplemented!();
| ^^^ referenced constant has errors
| ^^^^^---^
| |
| referenced constant has errors
error: aborting due to 3 previous errors
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0080`.

View File

@ -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

View File

@ -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(){}

View File

@ -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

View File

@ -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();
}

View File

@ -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`.