Unimplemented(String),
DerefFunctionPointer,
ExecuteMemory,
- BoundsCheck { len: O, index: O },
- Overflow(mir::BinOp),
- OverflowNeg,
- DivisionByZero,
- RemainderByZero,
Intrinsic(String),
InvalidChar(u128),
StackFrameLimitReached,
InfiniteLoop,
}
-
pub type InterpResult<'tcx, T = ()> = Result<T, InterpErrorInfo<'tcx>>;
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(..) =>
two",
Unreachable =>
"entered unreachable code",
- Panic { .. } =>
+ Panic(EvalErrorPanic::Panic{..}) =>
"the evaluated program panicked",
+ Panic(EvalErrorPanic::BoundsCheck{..}) =>
+ "array index out of bounds",
+ Panic(EvalErrorPanic::Overflow(mir::BinOp::Add)) =>
+ "attempt to add with overflow",
+ Panic(EvalErrorPanic::Overflow(mir::BinOp::Sub)) =>
+ "attempt to subtract with overflow",
+ Panic(EvalErrorPanic::Overflow(mir::BinOp::Mul)) =>
+ "attempt to multiply with overflow",
+ Panic(EvalErrorPanic::Overflow(mir::BinOp::Div)) =>
+ "attempt to divide with overflow",
+ Panic(EvalErrorPanic::Overflow(mir::BinOp::Rem)) =>
+ "attempt to calculate the remainder with overflow",
+ Panic(EvalErrorPanic::OverflowNeg) =>
+ "attempt to negate with overflow",
+ Panic(EvalErrorPanic::Overflow(mir::BinOp::Shr)) =>
+ "attempt to shift right with overflow",
+ Panic(EvalErrorPanic::Overflow(mir::BinOp::Shl)) =>
+ "attempt to shift left with overflow",
+ Panic(EvalErrorPanic::Overflow(op)) =>
+ bug!("{:?} cannot overflow", op),
+ Panic(EvalErrorPanic::DivisionByZero) =>
+ "attempt to divide by zero",
+ Panic(EvalErrorPanic::RemainderByZero) =>
+ "attempt to calculate the remainder with a divisor of zero",
ReadFromReturnPointer =>
"tried to read from the return pointer",
PathNotFound(_) =>
"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 =>
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) =>
write!(f, "incorrect alloc info: expected size {} and align {}, \
got size {} and align {}",
size.bytes(), align.bytes(), size2.bytes(), align2.bytes()),
- Panic { .. } =>
- write!(f, "the evaluated program panicked"),
+ Panic(EvalErrorPanic::Panic { ref msg, line, col, ref file }) =>
+ write!(f, "the evaluated program panicked at '{}', {}:{}:{}", msg, file, line, col),
+ Panic(EvalErrorPanic::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) =>
use rustc_macros::HashStable;
use super::{
- AllocId, InterpResult,
+ AllocId, InterpResult, EvalErrorPanic
};
/// Used by `check_in_alloc` to indicate context of check
#[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(EvalErrorPanic::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(EvalErrorPanic::Overflow(mir::BinOp::Add))) } else { Ok(res) }
}
}
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, EvalErrorPanic, InterpError::Panic, Scalar};
use crate::mir::visit::MirVisitable;
use crate::rustc_serialize as serialize;
use crate::ty::adjustment::PointerCast;
}
}
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(EvalErrorPanic::BoundsCheck { ref len, ref index }) = *msg {
+ Panic(EvalErrorPanic::BoundsCheck {
len: len.fold_with(folder),
index: index.fold_with(folder),
- }
+ })
} else {
msg.clone()
};
}
Assert { ref cond, ref msg, .. } => {
if cond.visit_with(visitor) {
- if let InterpError::BoundsCheck { ref len, ref index } = *msg {
+ if let Panic(EvalErrorPanic::BoundsCheck { ref len, ref index }) = *msg {
len.visit_with(visitor) || index.visit_with(visitor)
} else {
false
msg: & $($mutability)? AssertMessage<'tcx>,
location: Location) {
use crate::mir::interpret::InterpError::*;
- if let BoundsCheck { len, index } = msg {
+ use crate::mir::interpret::EvalErrorPanic::BoundsCheck;
+ if let Panic(BoundsCheck { len, index }) = msg {
self.visit_operand(len, location);
self.visit_operand(index, location);
}
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, EvalErrorPanic};
use rustc_target::abi::call::{ArgType, FnType, PassMode, IgnoreMode};
use rustc_target::spec::abi::Abi;
use crate::base;
// 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(EvalErrorPanic::OverflowNeg) = *msg {
const_cond = Some(expected);
}
}
// Put together the arguments to the panic entry point.
let (lang_item, args) = match *msg {
- InterpError::BoundsCheck { ref len, ref index } => {
+ InterpError::Panic(EvalErrorPanic::BoundsCheck { ref len, ref index }) => {
let len = self.codegen_operand(&mut bx, len).immediate();
let index = self.codegen_operand(&mut bx, index).immediate();
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, EvalErrorPanic};
+ if let Panic(EvalErrorPanic::BoundsCheck { ref len, ref index }) = *msg {
self.consume_operand(loc, (len, span), flow_state);
self.consume_operand(loc, (index, span), flow_state);
}
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, EvalErrorPanic::BoundsCheck};
+ if let Panic(BoundsCheck { ref len, ref index }) = *msg {
self.consume_operand(location, len);
self.consume_operand(location, index);
}
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, EvalErrorPanic};
use rustc::mir::tcx::PlaceTy;
use rustc::mir::visit::{PlaceContext, Visitor, NonMutatingUseContext};
use rustc::mir::*;
span_mirbug!(self, term, "bad Assert ({:?}, not bool", cond_ty);
}
- if let BoundsCheck { ref len, ref index } = *msg {
+ if let Panic(EvalErrorPanic::BoundsCheck { ref len, ref index }) = *msg {
if len.ty(body, tcx) != tcx.types.usize {
span_mirbug!(self, len, "bounds-check length non-usize {:?}", len)
}
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, EvalErrorPanic::BoundsCheck};
use rustc::mir::*;
use rustc::ty::{CanonicalUserTypeAnnotation, Variance};
),
);
- 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))
}
use crate::build::{BlockAnd, BlockAndExtension, Builder};
use crate::hair::*;
use rustc::middle::region;
-use rustc::mir::interpret::InterpError;
+use rustc::mir::interpret::{InterpError::Panic, EvalErrorPanic};
use rustc::mir::*;
use rustc::ty::{self, CanonicalUserTypeAnnotation, Ty, UpvarSubsts};
use syntax_pos::Span;
block,
Operand::Move(is_min),
false,
- InterpError::OverflowNeg,
+ Panic(EvalErrorPanic::OverflowNeg),
expr_span,
);
}
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(EvalErrorPanic::Overflow(op));
block = self.assert(block, Operand::Move(of), false, err, span);
// 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(EvalErrorPanic::DivisionByZero), Panic(EvalErrorPanic::Overflow(op)))
} else {
- (InterpError::RemainderByZero, InterpError::Overflow(op))
+ (Panic(EvalErrorPanic::RemainderByZero), Panic(EvalErrorPanic::Overflow(op)))
};
// Check for / 0
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, EvalErrorPanic, Scalar};
use super::{InterpCx, PlaceTy, Immediate, Machine, ImmTy};
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(EvalErrorPanic::DivisionByZero)),
+ Rem if r == 0 => return err!(Panic(EvalErrorPanic::RemainderByZero)),
Div => Some(i128::overflowing_div),
Rem => Some(i128::overflowing_rem),
Add => Some(i128::overflowing_add),
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(EvalErrorPanic::DivisionByZero)),
+ Rem if r == 0 => return err!(Panic(EvalErrorPanic::RemainderByZero)),
Div => u128::overflowing_div,
Rem => u128::overflowing_rem,
_ => bug!(),
use super::{
GlobalId, AllocId, Allocation, Scalar, InterpResult, Pointer, PointerArithmetic,
- InterpCx, Machine, AllocMap, AllocationExtra,
+ InterpCx, Machine, AllocMap, AllocationExtra, EvalErrorPanic,
RawConst, Immediate, ImmTy, ScalarMaybeUndef, Operand, OpTy, MemoryKind, LocalValue
};
// 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(EvalErrorPanic::BoundsCheck { len, index: field }));
}
stride * field
}
use rustc_target::spec::abi::Abi;
use super::{
- InterpResult, PointerArithmetic, InterpError, Scalar,
+ InterpResult, PointerArithmetic, InterpError, Scalar, EvalErrorPanic,
InterpCx, Machine, Immediate, OpTy, ImmTy, PlaceTy, MPlaceTy, StackPopCleanup, FnVal,
};
// Compute error message
use rustc::mir::interpret::InterpError::*;
return match *msg {
- BoundsCheck { ref len, ref index } => {
+ Panic(EvalErrorPanic::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(EvalErrorPanic::BoundsCheck { len, index }))
}
- Overflow(op) => Err(Overflow(op).into()),
- OverflowNeg => Err(OverflowNeg.into()),
- DivisionByZero => Err(DivisionByZero.into()),
- RemainderByZero => Err(RemainderByZero.into()),
+ Panic(EvalErrorPanic::Overflow(op)) =>
+ Err(Panic(EvalErrorPanic::Overflow(op)).into()),
+ Panic(EvalErrorPanic::OverflowNeg) =>
+ Err(Panic(EvalErrorPanic::OverflowNeg).into()),
+ Panic(EvalErrorPanic::DivisionByZero) =>
+ Err(Panic(EvalErrorPanic::DivisionByZero).into()),
+ Panic(EvalErrorPanic::RemainderByZero) =>
+ Err(Panic(EvalErrorPanic::RemainderByZero).into()),
GeneratorResumedAfterReturn |
GeneratorResumedAfterPanic => unimplemented!(),
_ => bug!(),
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, EvalErrorPanic};
use rustc::ty::{self, Instance, ParamEnv, Ty, TyCtxt};
use syntax_pos::{Span, DUMMY_SP};
use rustc::ty::subst::InternalSubsts;
// FIXME: implement
=> {},
- | Panic { .. }
- | BoundsCheck{..}
- | Overflow(_)
- | OverflowNeg
- | DivisionByZero
- | RemainderByZero
+ | Panic(EvalErrorPanic::Panic { .. })
+ | Panic(EvalErrorPanic::BoundsCheck{..})
+ | Panic(EvalErrorPanic::Overflow(_))
+ | Panic(EvalErrorPanic::OverflowNeg)
+ | Panic(EvalErrorPanic::DivisionByZero)
+ | Panic(EvalErrorPanic::RemainderByZero)
=> {
diagnostic.report_as_lint(
self.ecx.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(EvalErrorPanic::OverflowNeg));
}
}
UnOp::Not => {
)
} else {
if overflow {
- let err = InterpError::Overflow(op).into();
+ let err = Panic(EvalErrorPanic::Overflow(op)).into();
let _: Option<()> = self.use_ecx(source_info, |_| Err(err));
return None;
}
.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(EvalErrorPanic::Overflow(_)) |
+ Panic(EvalErrorPanic::OverflowNeg) |
+ Panic(EvalErrorPanic::DivisionByZero) |
+ Panic(EvalErrorPanic::RemainderByZero) => msg.description().to_owned(),
+ Panic(EvalErrorPanic::BoundsCheck { ref len, ref index }) => {
let len = self
.eval_operand(len, source_info)
.expect("len must be const");