Rollup merge of #60951 - saleemjaffer:mir_better_error_enum, r=oli-obk
more specific errors in src/librustc/mir/interpret/error.rs Implements [this](https://github.com/rust-rfcs/const-eval/issues/4)
This commit is contained in:
commit
52e9e44c7f
@ -228,6 +228,24 @@ impl<'tcx> From<InterpError<'tcx, u64>> for InterpErrorInfo<'tcx> {
|
||||
|
||||
pub type AssertMessage<'tcx> = InterpError<'tcx, mir::Operand<'tcx>>;
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
|
||||
pub enum PanicMessage<O> {
|
||||
Panic {
|
||||
msg: Symbol,
|
||||
line: u32,
|
||||
col: u32,
|
||||
file: Symbol,
|
||||
},
|
||||
BoundsCheck {
|
||||
len: O,
|
||||
index: O,
|
||||
},
|
||||
Overflow(mir::BinOp),
|
||||
OverflowNeg,
|
||||
DivisionByZero,
|
||||
RemainderByZero,
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
|
||||
pub enum InterpError<'tcx, O> {
|
||||
/// This variant is used by machines to signal their own errors that do not
|
||||
@ -266,11 +284,6 @@ pub enum InterpError<'tcx, O> {
|
||||
Unimplemented(String),
|
||||
DerefFunctionPointer,
|
||||
ExecuteMemory,
|
||||
BoundsCheck { len: O, index: O },
|
||||
Overflow(mir::BinOp),
|
||||
OverflowNeg,
|
||||
DivisionByZero,
|
||||
RemainderByZero,
|
||||
Intrinsic(String),
|
||||
InvalidChar(u128),
|
||||
StackFrameLimitReached,
|
||||
@ -298,12 +311,7 @@ pub enum InterpError<'tcx, O> {
|
||||
HeapAllocZeroBytes,
|
||||
HeapAllocNonPowerOfTwoAlignment(u64),
|
||||
Unreachable,
|
||||
Panic {
|
||||
msg: Symbol,
|
||||
line: u32,
|
||||
col: u32,
|
||||
file: Symbol,
|
||||
},
|
||||
Panic(PanicMessage<O>),
|
||||
ReadFromReturnPointer,
|
||||
PathNotFound(Vec<String>),
|
||||
UnimplementedTraitSelection,
|
||||
@ -369,8 +377,6 @@ impl<'tcx, O> InterpError<'tcx, O> {
|
||||
"tried to dereference a function pointer",
|
||||
ExecuteMemory =>
|
||||
"tried to treat a memory pointer as a function pointer",
|
||||
BoundsCheck{..} =>
|
||||
"array index out of bounds",
|
||||
Intrinsic(..) =>
|
||||
"intrinsic failed",
|
||||
NoMirFor(..) =>
|
||||
@ -422,8 +428,32 @@ impl<'tcx, O> InterpError<'tcx, O> {
|
||||
two",
|
||||
Unreachable =>
|
||||
"entered unreachable code",
|
||||
Panic { .. } =>
|
||||
Panic(PanicMessage::Panic{..}) =>
|
||||
"the evaluated program panicked",
|
||||
Panic(PanicMessage::BoundsCheck{..}) =>
|
||||
"array index out of bounds",
|
||||
Panic(PanicMessage::Overflow(mir::BinOp::Add)) =>
|
||||
"attempt to add with overflow",
|
||||
Panic(PanicMessage::Overflow(mir::BinOp::Sub)) =>
|
||||
"attempt to subtract with overflow",
|
||||
Panic(PanicMessage::Overflow(mir::BinOp::Mul)) =>
|
||||
"attempt to multiply with overflow",
|
||||
Panic(PanicMessage::Overflow(mir::BinOp::Div)) =>
|
||||
"attempt to divide with overflow",
|
||||
Panic(PanicMessage::Overflow(mir::BinOp::Rem)) =>
|
||||
"attempt to calculate the remainder with overflow",
|
||||
Panic(PanicMessage::OverflowNeg) =>
|
||||
"attempt to negate with overflow",
|
||||
Panic(PanicMessage::Overflow(mir::BinOp::Shr)) =>
|
||||
"attempt to shift right with overflow",
|
||||
Panic(PanicMessage::Overflow(mir::BinOp::Shl)) =>
|
||||
"attempt to shift left with overflow",
|
||||
Panic(PanicMessage::Overflow(op)) =>
|
||||
bug!("{:?} cannot overflow", op),
|
||||
Panic(PanicMessage::DivisionByZero) =>
|
||||
"attempt to divide by zero",
|
||||
Panic(PanicMessage::RemainderByZero) =>
|
||||
"attempt to calculate the remainder with a divisor of zero",
|
||||
ReadFromReturnPointer =>
|
||||
"tried to read from the return pointer",
|
||||
PathNotFound(_) =>
|
||||
@ -436,17 +466,6 @@ impl<'tcx, O> InterpError<'tcx, O> {
|
||||
"encountered overly generic constant",
|
||||
ReferencedConstant =>
|
||||
"referenced constant has errors",
|
||||
Overflow(mir::BinOp::Add) => "attempt to add with overflow",
|
||||
Overflow(mir::BinOp::Sub) => "attempt to subtract with overflow",
|
||||
Overflow(mir::BinOp::Mul) => "attempt to multiply with overflow",
|
||||
Overflow(mir::BinOp::Div) => "attempt to divide with overflow",
|
||||
Overflow(mir::BinOp::Rem) => "attempt to calculate the remainder with overflow",
|
||||
OverflowNeg => "attempt to negate with overflow",
|
||||
Overflow(mir::BinOp::Shr) => "attempt to shift right with overflow",
|
||||
Overflow(mir::BinOp::Shl) => "attempt to shift left with overflow",
|
||||
Overflow(op) => bug!("{:?} cannot overflow", op),
|
||||
DivisionByZero => "attempt to divide by zero",
|
||||
RemainderByZero => "attempt to calculate the remainder with a divisor of zero",
|
||||
GeneratorResumedAfterReturn => "generator resumed after completion",
|
||||
GeneratorResumedAfterPanic => "generator resumed after panicking",
|
||||
InfiniteLoop =>
|
||||
@ -493,8 +512,6 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for InterpError<'tcx, O> {
|
||||
callee_ty, caller_ty),
|
||||
FunctionArgCountMismatch =>
|
||||
write!(f, "tried to call a function with incorrect number of arguments"),
|
||||
BoundsCheck { ref len, ref index } =>
|
||||
write!(f, "index out of bounds: the len is {:?} but the index is {:?}", len, index),
|
||||
ReallocatedWrongMemoryKind(ref old, ref new) =>
|
||||
write!(f, "tried to reallocate memory from {} to {}", old, new),
|
||||
DeallocatedWrongMemoryKind(ref old, ref new) =>
|
||||
@ -518,8 +535,10 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for InterpError<'tcx, O> {
|
||||
write!(f, "incorrect alloc info: expected size {} and align {}, \
|
||||
got size {} and align {}",
|
||||
size.bytes(), align.bytes(), size2.bytes(), align2.bytes()),
|
||||
Panic { ref msg, line, col, ref file } =>
|
||||
Panic(PanicMessage::Panic { ref msg, line, col, ref file }) =>
|
||||
write!(f, "the evaluated program panicked at '{}', {}:{}:{}", msg, file, line, col),
|
||||
Panic(PanicMessage::BoundsCheck { ref len, ref index }) =>
|
||||
write!(f, "index out of bounds: the len is {:?} but the index is {:?}", len, index),
|
||||
InvalidDiscriminant(val) =>
|
||||
write!(f, "encountered invalid enum discriminant {}", val),
|
||||
Exit(code) =>
|
||||
|
@ -12,7 +12,7 @@ mod pointer;
|
||||
|
||||
pub use self::error::{
|
||||
InterpErrorInfo, InterpResult, InterpError, AssertMessage, ConstEvalErr, struct_error,
|
||||
FrameInfo, ConstEvalRawResult, ConstEvalResult, ErrorHandled,
|
||||
FrameInfo, ConstEvalRawResult, ConstEvalResult, ErrorHandled, PanicMessage
|
||||
};
|
||||
|
||||
pub use self::value::{Scalar, ScalarMaybeUndef, RawConst, ConstValue};
|
||||
|
@ -5,7 +5,7 @@ use crate::ty::layout::{self, HasDataLayout, Size};
|
||||
use rustc_macros::HashStable;
|
||||
|
||||
use super::{
|
||||
AllocId, InterpResult,
|
||||
AllocId, InterpResult, PanicMessage
|
||||
};
|
||||
|
||||
/// Used by `check_in_alloc` to indicate context of check
|
||||
@ -76,13 +76,13 @@ pub trait PointerArithmetic: layout::HasDataLayout {
|
||||
#[inline]
|
||||
fn offset<'tcx>(&self, val: u64, i: u64) -> InterpResult<'tcx, u64> {
|
||||
let (res, over) = self.overflowing_offset(val, i);
|
||||
if over { err!(Overflow(mir::BinOp::Add)) } else { Ok(res) }
|
||||
if over { err!(Panic(PanicMessage::Overflow(mir::BinOp::Add))) } else { Ok(res) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn signed_offset<'tcx>(&self, val: u64, i: i64) -> InterpResult<'tcx, u64> {
|
||||
let (res, over) = self.overflowing_signed_offset(val, i128::from(i));
|
||||
if over { err!(Overflow(mir::BinOp::Add)) } else { Ok(res) }
|
||||
if over { err!(Panic(PanicMessage::Overflow(mir::BinOp::Add))) } else { Ok(res) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
use crate::hir::def::{CtorKind, Namespace};
|
||||
use crate::hir::def_id::DefId;
|
||||
use crate::hir::{self, InlineAsm as HirInlineAsm};
|
||||
use crate::mir::interpret::{ConstValue, InterpError, Scalar};
|
||||
use crate::mir::interpret::{ConstValue, PanicMessage, InterpError::Panic, Scalar};
|
||||
use crate::mir::visit::MirVisitable;
|
||||
use crate::rustc_serialize as serialize;
|
||||
use crate::ty::adjustment::PointerCast;
|
||||
@ -3152,11 +3152,11 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
|
||||
}
|
||||
}
|
||||
Assert { ref cond, expected, ref msg, target, cleanup } => {
|
||||
let msg = if let InterpError::BoundsCheck { ref len, ref index } = *msg {
|
||||
InterpError::BoundsCheck {
|
||||
let msg = if let Panic(PanicMessage::BoundsCheck { ref len, ref index }) = *msg {
|
||||
Panic(PanicMessage::BoundsCheck {
|
||||
len: len.fold_with(folder),
|
||||
index: index.fold_with(folder),
|
||||
}
|
||||
})
|
||||
} else {
|
||||
msg.clone()
|
||||
};
|
||||
@ -3197,7 +3197,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
|
||||
}
|
||||
Assert { ref cond, ref msg, .. } => {
|
||||
if cond.visit_with(visitor) {
|
||||
if let InterpError::BoundsCheck { ref len, ref index } = *msg {
|
||||
if let Panic(PanicMessage::BoundsCheck { ref len, ref index }) = *msg {
|
||||
len.visit_with(visitor) || index.visit_with(visitor)
|
||||
} else {
|
||||
false
|
||||
|
@ -515,7 +515,8 @@ macro_rules! make_mir_visitor {
|
||||
msg: & $($mutability)? AssertMessage<'tcx>,
|
||||
location: Location) {
|
||||
use crate::mir::interpret::InterpError::*;
|
||||
if let BoundsCheck { len, index } = msg {
|
||||
use crate::mir::interpret::PanicMessage::BoundsCheck;
|
||||
if let Panic(BoundsCheck { len, index }) = msg {
|
||||
self.visit_operand(len, location);
|
||||
self.visit_operand(index, location);
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ use rustc::middle::lang_items;
|
||||
use rustc::ty::{self, Ty, TypeFoldable, Instance};
|
||||
use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, FnTypeExt};
|
||||
use rustc::mir::{self, Place, PlaceBase, Static, StaticKind};
|
||||
use rustc::mir::interpret::InterpError;
|
||||
use rustc::mir::interpret::{InterpError, PanicMessage};
|
||||
use rustc_target::abi::call::{ArgType, FnType, PassMode, IgnoreMode};
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use crate::base;
|
||||
@ -368,7 +368,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
// checked operation, just a comparison with the minimum
|
||||
// value, so we have to check for the assert message.
|
||||
if !bx.check_overflow() {
|
||||
if let mir::interpret::InterpError::OverflowNeg = *msg {
|
||||
if let InterpError::Panic(PanicMessage::OverflowNeg) = *msg {
|
||||
const_cond = Some(expected);
|
||||
}
|
||||
}
|
||||
@ -403,7 +403,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
|
||||
// Put together the arguments to the panic entry point.
|
||||
let (lang_item, args) = match *msg {
|
||||
InterpError::BoundsCheck { ref len, ref index } => {
|
||||
InterpError::Panic(PanicMessage::BoundsCheck { ref len, ref index }) => {
|
||||
let len = self.codegen_operand(&mut bx, len).immediate();
|
||||
let index = self.codegen_operand(&mut bx, index).immediate();
|
||||
|
||||
|
@ -733,8 +733,8 @@ impl<'cx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx
|
||||
cleanup: _,
|
||||
} => {
|
||||
self.consume_operand(loc, (cond, span), flow_state);
|
||||
use rustc::mir::interpret::InterpError::BoundsCheck;
|
||||
if let BoundsCheck { ref len, ref index } = *msg {
|
||||
use rustc::mir::interpret::{InterpError::Panic, PanicMessage};
|
||||
if let Panic(PanicMessage::BoundsCheck { ref len, ref index }) = *msg {
|
||||
self.consume_operand(loc, (len, span), flow_state);
|
||||
self.consume_operand(loc, (index, span), flow_state);
|
||||
}
|
||||
|
@ -207,8 +207,8 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
|
||||
cleanup: _,
|
||||
} => {
|
||||
self.consume_operand(location, cond);
|
||||
use rustc::mir::interpret::InterpError::BoundsCheck;
|
||||
if let BoundsCheck { ref len, ref index } = *msg {
|
||||
use rustc::mir::interpret::{InterpError::Panic, PanicMessage::BoundsCheck};
|
||||
if let Panic(BoundsCheck { ref len, ref index }) = *msg {
|
||||
self.consume_operand(location, len);
|
||||
self.consume_operand(location, index);
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ use rustc::infer::canonical::QueryRegionConstraints;
|
||||
use rustc::infer::outlives::env::RegionBoundPairs;
|
||||
use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin};
|
||||
use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc::mir::interpret::{InterpError::BoundsCheck, ConstValue};
|
||||
use rustc::mir::interpret::{InterpError::Panic, ConstValue, PanicMessage};
|
||||
use rustc::mir::tcx::PlaceTy;
|
||||
use rustc::mir::visit::{PlaceContext, Visitor, NonMutatingUseContext};
|
||||
use rustc::mir::*;
|
||||
@ -1606,7 +1606,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
span_mirbug!(self, term, "bad Assert ({:?}, not bool", cond_ty);
|
||||
}
|
||||
|
||||
if let BoundsCheck { ref len, ref index } = *msg {
|
||||
if let Panic(PanicMessage::BoundsCheck { ref len, ref index }) = *msg {
|
||||
if len.ty(body, tcx) != tcx.types.usize {
|
||||
span_mirbug!(self, len, "bounds-check length non-usize {:?}", len)
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ use crate::build::expr::category::Category;
|
||||
use crate::build::ForGuard::{OutsideGuard, RefWithinGuard};
|
||||
use crate::build::{BlockAnd, BlockAndExtension, Builder};
|
||||
use crate::hair::*;
|
||||
use rustc::mir::interpret::InterpError::BoundsCheck;
|
||||
use rustc::mir::interpret::{InterpError::Panic, PanicMessage::BoundsCheck};
|
||||
use rustc::mir::*;
|
||||
use rustc::ty::{CanonicalUserTypeAnnotation, Variance};
|
||||
|
||||
@ -105,10 +105,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
),
|
||||
);
|
||||
|
||||
let msg = BoundsCheck {
|
||||
let msg = Panic(BoundsCheck {
|
||||
len: Operand::Move(len),
|
||||
index: Operand::Copy(Place::from(idx)),
|
||||
};
|
||||
});
|
||||
let success = this.assert(block, Operand::Move(lt), true, msg, expr_span);
|
||||
success.and(slice.index(idx))
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ use crate::build::expr::category::{Category, RvalueFunc};
|
||||
use crate::build::{BlockAnd, BlockAndExtension, Builder};
|
||||
use crate::hair::*;
|
||||
use rustc::middle::region;
|
||||
use rustc::mir::interpret::InterpError;
|
||||
use rustc::mir::interpret::{InterpError::Panic, PanicMessage};
|
||||
use rustc::mir::*;
|
||||
use rustc::ty::{self, CanonicalUserTypeAnnotation, Ty, UpvarSubsts};
|
||||
use syntax_pos::Span;
|
||||
@ -101,7 +101,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
block,
|
||||
Operand::Move(is_min),
|
||||
false,
|
||||
InterpError::OverflowNeg,
|
||||
Panic(PanicMessage::OverflowNeg),
|
||||
expr_span,
|
||||
);
|
||||
}
|
||||
@ -401,7 +401,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
let val = result_value.clone().field(val_fld, ty);
|
||||
let of = result_value.field(of_fld, bool_ty);
|
||||
|
||||
let err = InterpError::Overflow(op);
|
||||
let err = Panic(PanicMessage::Overflow(op));
|
||||
|
||||
block = self.assert(block, Operand::Move(of), false, err, span);
|
||||
|
||||
@ -412,9 +412,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
// and 2. there are two possible failure cases, divide-by-zero and overflow.
|
||||
|
||||
let (zero_err, overflow_err) = if op == BinOp::Div {
|
||||
(InterpError::DivisionByZero, InterpError::Overflow(op))
|
||||
(Panic(PanicMessage::DivisionByZero), Panic(PanicMessage::Overflow(op)))
|
||||
} else {
|
||||
(InterpError::RemainderByZero, InterpError::Overflow(op))
|
||||
(Panic(PanicMessage::RemainderByZero), Panic(PanicMessage::Overflow(op)))
|
||||
};
|
||||
|
||||
// Check for / 0
|
||||
|
@ -7,7 +7,7 @@ use rustc::ty;
|
||||
use rustc::ty::layout::{LayoutOf, Primitive, Size};
|
||||
use rustc::mir::BinOp;
|
||||
use rustc::mir::interpret::{
|
||||
InterpResult, InterpError, Scalar,
|
||||
InterpResult, InterpError, Scalar, PanicMessage,
|
||||
};
|
||||
|
||||
use super::{
|
||||
@ -261,7 +261,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
let file = Symbol::intern(self.read_str(file_place)?);
|
||||
let line = self.read_scalar(line.into())?.to_u32()?;
|
||||
let col = self.read_scalar(col.into())?.to_u32()?;
|
||||
return Err(InterpError::Panic { msg, file, line, col }.into());
|
||||
return Err(InterpError::Panic(PanicMessage::Panic { msg, file, line, col }).into());
|
||||
} else if Some(def_id) == self.tcx.lang_items().begin_panic_fn() {
|
||||
assert!(args.len() == 2);
|
||||
// &'static str, &(&'static str, u32, u32)
|
||||
@ -279,7 +279,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
let file = Symbol::intern(self.read_str(file_place)?);
|
||||
let line = self.read_scalar(line.into())?.to_u32()?;
|
||||
let col = self.read_scalar(col.into())?.to_u32()?;
|
||||
return Err(InterpError::Panic { msg, file, line, col }.into());
|
||||
return Err(InterpError::Panic(PanicMessage::Panic { msg, file, line, col }).into());
|
||||
} else {
|
||||
return Ok(false);
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ use rustc::mir;
|
||||
use rustc::ty::{self, layout::TyLayout};
|
||||
use syntax::ast::FloatTy;
|
||||
use rustc_apfloat::Float;
|
||||
use rustc::mir::interpret::{InterpResult, Scalar};
|
||||
use rustc::mir::interpret::{InterpResult, PanicMessage, Scalar};
|
||||
|
||||
use super::{InterpCx, PlaceTy, Immediate, Machine, ImmTy};
|
||||
|
||||
@ -173,8 +173,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
return Ok((Scalar::from_bool(op(&l, &r)), false));
|
||||
}
|
||||
let op: Option<fn(i128, i128) -> (i128, bool)> = match bin_op {
|
||||
Div if r == 0 => return err!(DivisionByZero),
|
||||
Rem if r == 0 => return err!(RemainderByZero),
|
||||
Div if r == 0 => return err!(Panic(PanicMessage::DivisionByZero)),
|
||||
Rem if r == 0 => return err!(Panic(PanicMessage::RemainderByZero)),
|
||||
Div => Some(i128::overflowing_div),
|
||||
Rem => Some(i128::overflowing_rem),
|
||||
Add => Some(i128::overflowing_add),
|
||||
@ -231,8 +231,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
Add => u128::overflowing_add,
|
||||
Sub => u128::overflowing_sub,
|
||||
Mul => u128::overflowing_mul,
|
||||
Div if r == 0 => return err!(DivisionByZero),
|
||||
Rem if r == 0 => return err!(RemainderByZero),
|
||||
Div if r == 0 => return err!(Panic(PanicMessage::DivisionByZero)),
|
||||
Rem if r == 0 => return err!(Panic(PanicMessage::RemainderByZero)),
|
||||
Div => u128::overflowing_div,
|
||||
Rem => u128::overflowing_rem,
|
||||
_ => bug!(),
|
||||
|
@ -13,7 +13,7 @@ use rustc::ty::TypeFoldable;
|
||||
|
||||
use super::{
|
||||
GlobalId, AllocId, Allocation, Scalar, InterpResult, Pointer, PointerArithmetic,
|
||||
InterpCx, Machine, AllocMap, AllocationExtra,
|
||||
InterpCx, Machine, AllocMap, AllocationExtra, PanicMessage,
|
||||
RawConst, Immediate, ImmTy, ScalarMaybeUndef, Operand, OpTy, MemoryKind, LocalValue
|
||||
};
|
||||
|
||||
@ -356,7 +356,7 @@ where
|
||||
// This can be violated because this runs during promotion on code where the
|
||||
// type system has not yet ensured that such things don't happen.
|
||||
debug!("tried to access element {} of array/slice with length {}", field, len);
|
||||
return err!(BoundsCheck { len, index: field });
|
||||
return err!(Panic(PanicMessage::BoundsCheck { len, index: field }));
|
||||
}
|
||||
stride * field
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ use syntax::source_map::Span;
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
use super::{
|
||||
InterpResult, PointerArithmetic, InterpError, Scalar,
|
||||
InterpResult, PointerArithmetic, InterpError, Scalar, PanicMessage,
|
||||
InterpCx, Machine, Immediate, OpTy, ImmTy, PlaceTy, MPlaceTy, StackPopCleanup, FnVal,
|
||||
};
|
||||
|
||||
@ -137,19 +137,23 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
// Compute error message
|
||||
use rustc::mir::interpret::InterpError::*;
|
||||
return match *msg {
|
||||
BoundsCheck { ref len, ref index } => {
|
||||
Panic(PanicMessage::BoundsCheck { ref len, ref index }) => {
|
||||
let len = self.read_immediate(self.eval_operand(len, None)?)
|
||||
.expect("can't eval len").to_scalar()?
|
||||
.to_bits(self.memory().pointer_size())? as u64;
|
||||
let index = self.read_immediate(self.eval_operand(index, None)?)
|
||||
.expect("can't eval index").to_scalar()?
|
||||
.to_bits(self.memory().pointer_size())? as u64;
|
||||
err!(BoundsCheck { len, index })
|
||||
err!(Panic(PanicMessage::BoundsCheck { len, index }))
|
||||
}
|
||||
Overflow(op) => Err(Overflow(op).into()),
|
||||
OverflowNeg => Err(OverflowNeg.into()),
|
||||
DivisionByZero => Err(DivisionByZero.into()),
|
||||
RemainderByZero => Err(RemainderByZero.into()),
|
||||
Panic(PanicMessage::Overflow(op)) =>
|
||||
Err(Panic(PanicMessage::Overflow(op)).into()),
|
||||
Panic(PanicMessage::OverflowNeg) =>
|
||||
Err(Panic(PanicMessage::OverflowNeg).into()),
|
||||
Panic(PanicMessage::DivisionByZero) =>
|
||||
Err(Panic(PanicMessage::DivisionByZero).into()),
|
||||
Panic(PanicMessage::RemainderByZero) =>
|
||||
Err(Panic(PanicMessage::RemainderByZero).into()),
|
||||
GeneratorResumedAfterReturn |
|
||||
GeneratorResumedAfterPanic => unimplemented!(),
|
||||
_ => bug!(),
|
||||
|
@ -13,7 +13,7 @@ use rustc::mir::{
|
||||
use rustc::mir::visit::{
|
||||
Visitor, PlaceContext, MutatingUseContext, MutVisitor, NonMutatingUseContext,
|
||||
};
|
||||
use rustc::mir::interpret::{InterpError, Scalar, GlobalId, InterpResult};
|
||||
use rustc::mir::interpret::{InterpError::Panic, Scalar, GlobalId, InterpResult, PanicMessage};
|
||||
use rustc::ty::{self, Instance, ParamEnv, Ty, TyCtxt};
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
use rustc::ty::subst::InternalSubsts;
|
||||
@ -339,12 +339,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||
// FIXME: implement
|
||||
=> {},
|
||||
|
||||
| Panic { .. }
|
||||
| BoundsCheck{..}
|
||||
| Overflow(_)
|
||||
| OverflowNeg
|
||||
| DivisionByZero
|
||||
| RemainderByZero
|
||||
| Panic(_)
|
||||
=> {
|
||||
diagnostic.report_as_lint(
|
||||
self.ecx.tcx,
|
||||
@ -522,7 +517,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||
// Need to do overflow check here: For actual CTFE, MIR
|
||||
// generation emits code that does this before calling the op.
|
||||
if prim.to_bits()? == (1 << (prim.layout.size.bits() - 1)) {
|
||||
return err!(OverflowNeg);
|
||||
return err!(Panic(PanicMessage::OverflowNeg));
|
||||
}
|
||||
}
|
||||
UnOp::Not => {
|
||||
@ -600,7 +595,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||
)
|
||||
} else {
|
||||
if overflow {
|
||||
let err = InterpError::Overflow(op).into();
|
||||
let err = Panic(PanicMessage::Overflow(op)).into();
|
||||
let _: Option<()> = self.use_ecx(source_info, |_| Err(err));
|
||||
return None;
|
||||
}
|
||||
@ -838,11 +833,11 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
|
||||
.expect("some part of a failing const eval must be local");
|
||||
use rustc::mir::interpret::InterpError::*;
|
||||
let msg = match msg {
|
||||
Overflow(_) |
|
||||
OverflowNeg |
|
||||
DivisionByZero |
|
||||
RemainderByZero => msg.description().to_owned(),
|
||||
BoundsCheck { ref len, ref index } => {
|
||||
Panic(PanicMessage::Overflow(_)) |
|
||||
Panic(PanicMessage::OverflowNeg) |
|
||||
Panic(PanicMessage::DivisionByZero) |
|
||||
Panic(PanicMessage::RemainderByZero) => msg.description().to_owned(),
|
||||
Panic(PanicMessage::BoundsCheck { ref len, ref index }) => {
|
||||
let len = self
|
||||
.eval_operand(len, source_info)
|
||||
.expect("len must be const");
|
||||
|
Loading…
Reference in New Issue
Block a user