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:
commit
9ac372568b
@ -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);
|
||||
|
@ -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> {
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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",
|
||||
|
@ -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 => {
|
||||
|
@ -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(),
|
||||
})))
|
||||
}
|
||||
},
|
||||
|
@ -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 \
|
||||
|
@ -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())),
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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 @@ 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();
|
||||
}
|
||||
|
@ -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
|
||||
},
|
||||
}
|
||||
|
@ -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
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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() {
|
||||
|
@ -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,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);
|
||||
|
@ -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 @@ 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;
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 @@ const TUP: (usize,) = 5usize << 64;
|
||||
//~^ 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 @@ 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
|
||||
}
|
||||
|
@ -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"),
|
||||
}
|
||||
}
|
||||
|
@ -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"),
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
|
@ -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() {
|
||||
|
@ -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
|
||||
|
||||
|
@ -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`.
|
@ -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
|
||||
}
|
||||
|
@ -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`.
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
static FOO: i32 = [][0];
|
||||
//~^ ERROR E0080
|
||||
//~| ERROR E0080
|
||||
|
||||
fn main() {
|
||||
let array = [std::env::args().len()];
|
||||
|
@ -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`.
|
||||
|
118
src/test/ui/const-eval/issue-43197.nll.stderr
Normal file
118
src/test/ui/const-eval/issue-43197.nll.stderr
Normal 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`.
|
@ -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
|
||||
}
|
||||
|
@ -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`.
|
||||
|
39
src/test/ui/const-eval/issue-44578.nll.stderr
Normal file
39
src/test/ui/const-eval/issue-44578.nll.stderr
Normal 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`.
|
@ -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
|
||||
}
|
||||
|
@ -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`.
|
||||
|
43
src/test/ui/const-eval/issue-50814-2.rs
Normal file
43
src/test/ui/const-eval/issue-50814-2.rs
Normal 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>());
|
||||
}
|
20
src/test/ui/const-eval/issue-50814-2.stderr
Normal file
20
src/test/ui/const-eval/issue-50814-2.stderr
Normal 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`.
|
33
src/test/ui/const-eval/issue-50814.rs
Normal file
33
src/test/ui/const-eval/issue-50814.rs
Normal 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);
|
||||
}
|
20
src/test/ui/const-eval/issue-50814.stderr
Normal file
20
src/test/ui/const-eval/issue-50814.stderr
Normal 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`.
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
||||
|
@ -21,4 +21,5 @@ const LEN: usize = ONE - TWO;
|
||||
fn main() {
|
||||
let a: [i8; LEN] = unimplemented!();
|
||||
//~^ ERROR E0080
|
||||
//~| ERROR E0080
|
||||
}
|
||||
|
@ -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`.
|
||||
|
@ -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(){}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 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`.
|
||||
|
Loading…
Reference in New Issue
Block a user