Merge ConstMathError into EvalErrorKind
This commit is contained in:
parent
671b2a5964
commit
cefcf0548e
12 changed files with 65 additions and 115 deletions
|
@ -525,16 +525,26 @@ impl_stable_hash_for!(struct ty::GenericPredicates<'tcx> {
|
||||||
predicates
|
predicates
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
|
impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
|
||||||
for ::mir::interpret::EvalError<'gcx> {
|
for ::mir::interpret::EvalError<'gcx> {
|
||||||
|
fn hash_stable<W: StableHasherResult>(&self,
|
||||||
|
hcx: &mut StableHashingContext<'a>,
|
||||||
|
hasher: &mut StableHasher<W>) {
|
||||||
|
self.kind.hash_stable(hcx, hasher)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'gcx> HashStable<StableHashingContext<'a>>
|
||||||
|
for ::mir::interpret::EvalErrorKind<'gcx> {
|
||||||
fn hash_stable<W: StableHasherResult>(&self,
|
fn hash_stable<W: StableHasherResult>(&self,
|
||||||
hcx: &mut StableHashingContext<'a>,
|
hcx: &mut StableHashingContext<'a>,
|
||||||
hasher: &mut StableHasher<W>) {
|
hasher: &mut StableHasher<W>) {
|
||||||
use mir::interpret::EvalErrorKind::*;
|
use mir::interpret::EvalErrorKind::*;
|
||||||
|
|
||||||
mem::discriminant(&self.kind).hash_stable(hcx, hasher);
|
mem::discriminant(&self).hash_stable(hcx, hasher);
|
||||||
|
|
||||||
match self.kind {
|
match *self {
|
||||||
DanglingPointerDeref |
|
DanglingPointerDeref |
|
||||||
DoubleFree |
|
DoubleFree |
|
||||||
InvalidMemoryAccess |
|
InvalidMemoryAccess |
|
||||||
|
@ -565,8 +575,10 @@ for ::mir::interpret::EvalError<'gcx> {
|
||||||
TypeckError |
|
TypeckError |
|
||||||
DerefFunctionPointer |
|
DerefFunctionPointer |
|
||||||
ExecuteMemory |
|
ExecuteMemory |
|
||||||
ReferencedConstant |
|
OverflowNeg |
|
||||||
OverflowingMath => {}
|
RemainderByZero |
|
||||||
|
DivisionByZero |
|
||||||
|
ReferencedConstant => {}
|
||||||
MachineError(ref err) => err.hash_stable(hcx, hasher),
|
MachineError(ref err) => err.hash_stable(hcx, hasher),
|
||||||
FunctionPointerTyMismatch(a, b) => {
|
FunctionPointerTyMismatch(a, b) => {
|
||||||
a.hash_stable(hcx, hasher);
|
a.hash_stable(hcx, hasher);
|
||||||
|
@ -590,10 +602,6 @@ for ::mir::interpret::EvalError<'gcx> {
|
||||||
a.hash_stable(hcx, hasher);
|
a.hash_stable(hcx, hasher);
|
||||||
b.hash_stable(hcx, hasher)
|
b.hash_stable(hcx, hasher)
|
||||||
},
|
},
|
||||||
Math(sp, ref err) => {
|
|
||||||
sp.hash_stable(hcx, hasher);
|
|
||||||
err.hash_stable(hcx, hasher)
|
|
||||||
},
|
|
||||||
Intrinsic(ref s) => s.hash_stable(hcx, hasher),
|
Intrinsic(ref s) => s.hash_stable(hcx, hasher),
|
||||||
InvalidChar(c) => c.hash_stable(hcx, hasher),
|
InvalidChar(c) => c.hash_stable(hcx, hasher),
|
||||||
AbiViolation(ref s) => s.hash_stable(hcx, hasher),
|
AbiViolation(ref s) => s.hash_stable(hcx, hasher),
|
||||||
|
@ -665,27 +673,11 @@ for ::mir::interpret::EvalError<'gcx> {
|
||||||
Layout(lay) => lay.hash_stable(hcx, hasher),
|
Layout(lay) => lay.hash_stable(hcx, hasher),
|
||||||
HeapAllocNonPowerOfTwoAlignment(n) => n.hash_stable(hcx, hasher),
|
HeapAllocNonPowerOfTwoAlignment(n) => n.hash_stable(hcx, hasher),
|
||||||
PathNotFound(ref v) => v.hash_stable(hcx, hasher),
|
PathNotFound(ref v) => v.hash_stable(hcx, hasher),
|
||||||
|
Overflow(op) => op.hash_stable(hcx, hasher),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_stable_hash_for!(enum mir::interpret::ConstMathErr {
|
|
||||||
Overflow(op),
|
|
||||||
DivisionByZero,
|
|
||||||
RemainderByZero,
|
|
||||||
});
|
|
||||||
|
|
||||||
impl_stable_hash_for!(enum mir::interpret::Op {
|
|
||||||
Add,
|
|
||||||
Sub,
|
|
||||||
Mul,
|
|
||||||
Div,
|
|
||||||
Rem,
|
|
||||||
Shr,
|
|
||||||
Shl,
|
|
||||||
Neg,
|
|
||||||
});
|
|
||||||
|
|
||||||
impl_stable_hash_for!(enum mir::interpret::Lock {
|
impl_stable_hash_for!(enum mir::interpret::Lock {
|
||||||
NoLock,
|
NoLock,
|
||||||
WriteLock(dl),
|
WriteLock(dl),
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
use std::error::Error;
|
|
||||||
use std::{fmt, env};
|
use std::{fmt, env};
|
||||||
|
|
||||||
use mir;
|
use mir;
|
||||||
|
@ -30,7 +29,7 @@ impl<'tcx> From<EvalErrorKind<'tcx>> for EvalError<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone, RustcEncodable, RustcDecodable)]
|
||||||
pub enum EvalErrorKind<'tcx> {
|
pub enum EvalErrorKind<'tcx> {
|
||||||
/// This variant is used by machines to signal their own errors that do not
|
/// This variant is used by machines to signal their own errors that do not
|
||||||
/// match an existing variant
|
/// match an existing variant
|
||||||
|
@ -60,9 +59,11 @@ pub enum EvalErrorKind<'tcx> {
|
||||||
DerefFunctionPointer,
|
DerefFunctionPointer,
|
||||||
ExecuteMemory,
|
ExecuteMemory,
|
||||||
ArrayIndexOutOfBounds(Span, u64, u64),
|
ArrayIndexOutOfBounds(Span, u64, u64),
|
||||||
Math(Span, ConstMathErr),
|
Overflow(mir::BinOp),
|
||||||
|
OverflowNeg,
|
||||||
|
DivisionByZero,
|
||||||
|
RemainderByZero,
|
||||||
Intrinsic(String),
|
Intrinsic(String),
|
||||||
OverflowingMath,
|
|
||||||
InvalidChar(u128),
|
InvalidChar(u128),
|
||||||
StackFrameLimitReached,
|
StackFrameLimitReached,
|
||||||
OutOfTls,
|
OutOfTls,
|
||||||
|
@ -124,10 +125,10 @@ pub enum EvalErrorKind<'tcx> {
|
||||||
|
|
||||||
pub type EvalResult<'tcx, T = ()> = Result<T, EvalError<'tcx>>;
|
pub type EvalResult<'tcx, T = ()> = Result<T, EvalError<'tcx>>;
|
||||||
|
|
||||||
impl<'tcx> Error for EvalError<'tcx> {
|
impl<'tcx> EvalErrorKind<'tcx> {
|
||||||
fn description(&self) -> &str {
|
pub fn description(&self) -> &str {
|
||||||
use self::EvalErrorKind::*;
|
use self::EvalErrorKind::*;
|
||||||
match self.kind {
|
match *self {
|
||||||
MachineError(ref inner) => inner,
|
MachineError(ref inner) => inner,
|
||||||
FunctionPointerTyMismatch(..) =>
|
FunctionPointerTyMismatch(..) =>
|
||||||
"tried to call a function through a function pointer of a different type",
|
"tried to call a function through a function pointer of a different type",
|
||||||
|
@ -176,12 +177,8 @@ impl<'tcx> Error for EvalError<'tcx> {
|
||||||
"tried to treat a memory pointer as a function pointer",
|
"tried to treat a memory pointer as a function pointer",
|
||||||
ArrayIndexOutOfBounds(..) =>
|
ArrayIndexOutOfBounds(..) =>
|
||||||
"array index out of bounds",
|
"array index out of bounds",
|
||||||
Math(..) =>
|
|
||||||
"mathematical operation failed",
|
|
||||||
Intrinsic(..) =>
|
Intrinsic(..) =>
|
||||||
"intrinsic failed",
|
"intrinsic failed",
|
||||||
OverflowingMath =>
|
|
||||||
"attempted to do overflowing math",
|
|
||||||
NoMirFor(..) =>
|
NoMirFor(..) =>
|
||||||
"mir not found",
|
"mir not found",
|
||||||
InvalidChar(..) =>
|
InvalidChar(..) =>
|
||||||
|
@ -239,6 +236,17 @@ impl<'tcx> Error for EvalError<'tcx> {
|
||||||
"encountered constants with type errors, stopping evaluation",
|
"encountered constants with type errors, stopping evaluation",
|
||||||
ReferencedConstant =>
|
ReferencedConstant =>
|
||||||
"referenced constant has errors",
|
"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",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -280,8 +288,6 @@ impl<'tcx> fmt::Display for EvalError<'tcx> {
|
||||||
write!(f, "tried to reallocate memory from {} to {}", old, new),
|
write!(f, "tried to reallocate memory from {} to {}", old, new),
|
||||||
DeallocatedWrongMemoryKind(ref old, ref new) =>
|
DeallocatedWrongMemoryKind(ref old, ref new) =>
|
||||||
write!(f, "tried to deallocate {} memory but gave {} as the kind", old, new),
|
write!(f, "tried to deallocate {} memory but gave {} as the kind", old, new),
|
||||||
Math(_, ref err) =>
|
|
||||||
write!(f, "{}", err.description()),
|
|
||||||
Intrinsic(ref err) =>
|
Intrinsic(ref err) =>
|
||||||
write!(f, "{}", err),
|
write!(f, "{}", err),
|
||||||
InvalidChar(c) =>
|
InvalidChar(c) =>
|
||||||
|
@ -299,45 +305,7 @@ impl<'tcx> fmt::Display for EvalError<'tcx> {
|
||||||
write!(f, "{}", inner),
|
write!(f, "{}", inner),
|
||||||
IncorrectAllocationInformation(size, size2, align, align2) =>
|
IncorrectAllocationInformation(size, size2, align, align2) =>
|
||||||
write!(f, "incorrect alloc info: expected size {} and align {}, got size {} and align {}", size, align, size2, align2),
|
write!(f, "incorrect alloc info: expected size {} and align {}, got size {} and align {}", size, align, size2, align2),
|
||||||
_ => write!(f, "{}", self.description()),
|
_ => write!(f, "{}", self.kind.description()),
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, RustcEncodable, RustcDecodable)]
|
|
||||||
pub enum ConstMathErr {
|
|
||||||
Overflow(Op),
|
|
||||||
DivisionByZero,
|
|
||||||
RemainderByZero,
|
|
||||||
}
|
|
||||||
pub use self::ConstMathErr::*;
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, RustcEncodable, RustcDecodable)]
|
|
||||||
pub enum Op {
|
|
||||||
Add,
|
|
||||||
Sub,
|
|
||||||
Mul,
|
|
||||||
Div,
|
|
||||||
Rem,
|
|
||||||
Shr,
|
|
||||||
Shl,
|
|
||||||
Neg,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ConstMathErr {
|
|
||||||
pub fn description(&self) -> &'static str {
|
|
||||||
use self::Op::*;
|
|
||||||
match *self {
|
|
||||||
Overflow(Add) => "attempt to add with overflow",
|
|
||||||
Overflow(Sub) => "attempt to subtract with overflow",
|
|
||||||
Overflow(Mul) => "attempt to multiply with overflow",
|
|
||||||
Overflow(Div) => "attempt to divide with overflow",
|
|
||||||
Overflow(Rem) => "attempt to calculate the remainder with overflow",
|
|
||||||
Overflow(Neg) => "attempt to negate with overflow",
|
|
||||||
Overflow(Shr) => "attempt to shift right with overflow",
|
|
||||||
Overflow(Shl) => "attempt to shift left with overflow",
|
|
||||||
DivisionByZero => "attempt to divide by zero",
|
|
||||||
RemainderByZero => "attempt to calculate the remainder with a divisor of zero",
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ macro_rules! err {
|
||||||
mod error;
|
mod error;
|
||||||
mod value;
|
mod value;
|
||||||
|
|
||||||
pub use self::error::{EvalError, EvalResult, EvalErrorKind, Op, ConstMathErr};
|
pub use self::error::{EvalError, EvalResult, EvalErrorKind};
|
||||||
|
|
||||||
pub use self::value::{PrimVal, PrimValKind, Value, Pointer};
|
pub use self::value::{PrimVal, PrimValKind, Value, Pointer};
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ use std::iter;
|
||||||
use syntax::ast::Mutability;
|
use syntax::ast::Mutability;
|
||||||
use rustc_serialize::{Encoder, Decoder, Decodable, Encodable};
|
use rustc_serialize::{Encoder, Decoder, Decodable, Encodable};
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
|
||||||
pub enum Lock {
|
pub enum Lock {
|
||||||
NoLock,
|
NoLock,
|
||||||
WriteLock(DynamicLifetime),
|
WriteLock(DynamicLifetime),
|
||||||
|
@ -31,13 +31,13 @@ pub enum Lock {
|
||||||
ReadLock(Vec<DynamicLifetime>),
|
ReadLock(Vec<DynamicLifetime>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
|
||||||
pub struct DynamicLifetime {
|
pub struct DynamicLifetime {
|
||||||
pub frame: usize,
|
pub frame: usize,
|
||||||
pub region: Option<region::Scope>, // "None" indicates "until the function ends"
|
pub region: Option<region::Scope>, // "None" indicates "until the function ends"
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable)]
|
||||||
pub enum AccessKind {
|
pub enum AccessKind {
|
||||||
Read,
|
Read,
|
||||||
Write,
|
Write,
|
||||||
|
@ -88,12 +88,12 @@ pub trait PointerArithmetic: layout::HasDataLayout {
|
||||||
|
|
||||||
fn signed_offset<'tcx>(self, val: u64, i: i64) -> EvalResult<'tcx, u64> {
|
fn signed_offset<'tcx>(self, val: u64, i: i64) -> EvalResult<'tcx, u64> {
|
||||||
let (res, over) = self.overflowing_signed_offset(val, i as i128);
|
let (res, over) = self.overflowing_signed_offset(val, i as i128);
|
||||||
if over { err!(OverflowingMath) } else { Ok(res) }
|
if over { err!(Overflow(mir::BinOp::Add)) } else { Ok(res) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn offset<'tcx>(self, val: u64, i: u64) -> EvalResult<'tcx, u64> {
|
fn offset<'tcx>(self, val: u64, i: u64) -> EvalResult<'tcx, u64> {
|
||||||
let (res, over) = self.overflowing_offset(val, i);
|
let (res, over) = self.overflowing_offset(val, i);
|
||||||
if over { err!(OverflowingMath) } else { Ok(res) }
|
if over { err!(Overflow(mir::BinOp::Add)) } else { Ok(res) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wrapping_signed_offset(self, val: u64, i: i64) -> u64 {
|
fn wrapping_signed_offset(self, val: u64, i: i64) -> u64 {
|
||||||
|
|
|
@ -25,7 +25,7 @@ use rustc_serialize as serialize;
|
||||||
use hir::def::CtorKind;
|
use hir::def::CtorKind;
|
||||||
use hir::def_id::DefId;
|
use hir::def_id::DefId;
|
||||||
use mir::visit::MirVisitable;
|
use mir::visit::MirVisitable;
|
||||||
use mir::interpret::{Value, PrimVal, ConstMathErr};
|
use mir::interpret::{Value, PrimVal, EvalErrorKind};
|
||||||
use ty::subst::{Subst, Substs};
|
use ty::subst::{Subst, Substs};
|
||||||
use ty::{self, AdtDef, CanonicalTy, ClosureSubsts, Region, Ty, TyCtxt, GeneratorInterior};
|
use ty::{self, AdtDef, CanonicalTy, ClosureSubsts, Region, Ty, TyCtxt, GeneratorInterior};
|
||||||
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
|
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
|
||||||
|
@ -1211,7 +1211,7 @@ pub enum AssertMessage<'tcx> {
|
||||||
len: Operand<'tcx>,
|
len: Operand<'tcx>,
|
||||||
index: Operand<'tcx>
|
index: Operand<'tcx>
|
||||||
},
|
},
|
||||||
Math(ConstMathErr),
|
Math(EvalErrorKind<'tcx>),
|
||||||
GeneratorResumedAfterReturn,
|
GeneratorResumedAfterReturn,
|
||||||
GeneratorResumedAfterPanic,
|
GeneratorResumedAfterPanic,
|
||||||
}
|
}
|
||||||
|
@ -1920,9 +1920,9 @@ pub fn print_miri_value<W: Write>(value: Value, ty: Ty, f: &mut W) -> fmt::Resul
|
||||||
(Value::ByVal(PrimVal::Bytes(0)), &TyBool) => write!(f, "false"),
|
(Value::ByVal(PrimVal::Bytes(0)), &TyBool) => write!(f, "false"),
|
||||||
(Value::ByVal(PrimVal::Bytes(1)), &TyBool) => write!(f, "true"),
|
(Value::ByVal(PrimVal::Bytes(1)), &TyBool) => write!(f, "true"),
|
||||||
(Value::ByVal(PrimVal::Bytes(bits)), &TyFloat(ast::FloatTy::F32)) =>
|
(Value::ByVal(PrimVal::Bytes(bits)), &TyFloat(ast::FloatTy::F32)) =>
|
||||||
write!(f, "{}", Single::from_bits(bits)),
|
write!(f, "{}f32", Single::from_bits(bits)),
|
||||||
(Value::ByVal(PrimVal::Bytes(bits)), &TyFloat(ast::FloatTy::F64)) =>
|
(Value::ByVal(PrimVal::Bytes(bits)), &TyFloat(ast::FloatTy::F64)) =>
|
||||||
write!(f, "{}", Double::from_bits(bits)),
|
write!(f, "{}f64", Double::from_bits(bits)),
|
||||||
(Value::ByVal(PrimVal::Bytes(n)), &TyUint(ui)) => write!(f, "{:?}{}", n, ui),
|
(Value::ByVal(PrimVal::Bytes(n)), &TyUint(ui)) => write!(f, "{:?}{}", n, ui),
|
||||||
(Value::ByVal(PrimVal::Bytes(n)), &TyInt(i)) => write!(f, "{:?}{}", n as i128, i),
|
(Value::ByVal(PrimVal::Bytes(n)), &TyInt(i)) => write!(f, "{:?}{}", n as i128, i),
|
||||||
(Value::ByVal(PrimVal::Bytes(n)), &TyChar) =>
|
(Value::ByVal(PrimVal::Bytes(n)), &TyChar) =>
|
||||||
|
|
|
@ -149,7 +149,7 @@ pub const FAT_PTR_ADDR: usize = 0;
|
||||||
/// - For a slice, this is the length.
|
/// - For a slice, this is the length.
|
||||||
pub const FAT_PTR_EXTRA: usize = 1;
|
pub const FAT_PTR_EXTRA: usize = 1;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
|
||||||
pub enum LayoutError<'tcx> {
|
pub enum LayoutError<'tcx> {
|
||||||
Unknown(Ty<'tcx>),
|
Unknown(Ty<'tcx>),
|
||||||
SizeOverflow(Ty<'tcx>)
|
SizeOverflow(Ty<'tcx>)
|
||||||
|
|
|
@ -505,9 +505,7 @@ impl<'a, 'tcx> Lift<'tcx> for interpret::EvalError<'a> {
|
||||||
DerefFunctionPointer => DerefFunctionPointer,
|
DerefFunctionPointer => DerefFunctionPointer,
|
||||||
ExecuteMemory => ExecuteMemory,
|
ExecuteMemory => ExecuteMemory,
|
||||||
ArrayIndexOutOfBounds(sp, a, b) => ArrayIndexOutOfBounds(sp, a, b),
|
ArrayIndexOutOfBounds(sp, a, b) => ArrayIndexOutOfBounds(sp, a, b),
|
||||||
Math(sp, ref err) => Math(sp, err.clone()),
|
|
||||||
Intrinsic(ref s) => Intrinsic(s.clone()),
|
Intrinsic(ref s) => Intrinsic(s.clone()),
|
||||||
OverflowingMath => OverflowingMath,
|
|
||||||
InvalidChar(c) => InvalidChar(c),
|
InvalidChar(c) => InvalidChar(c),
|
||||||
StackFrameLimitReached => StackFrameLimitReached,
|
StackFrameLimitReached => StackFrameLimitReached,
|
||||||
OutOfTls => OutOfTls,
|
OutOfTls => OutOfTls,
|
||||||
|
@ -568,6 +566,10 @@ impl<'a, 'tcx> Lift<'tcx> for interpret::EvalError<'a> {
|
||||||
UnimplementedTraitSelection => UnimplementedTraitSelection,
|
UnimplementedTraitSelection => UnimplementedTraitSelection,
|
||||||
TypeckError => TypeckError,
|
TypeckError => TypeckError,
|
||||||
ReferencedConstant => ReferencedConstant,
|
ReferencedConstant => ReferencedConstant,
|
||||||
|
OverflowNeg => OverflowNeg,
|
||||||
|
Overflow(op) => Overflow(op),
|
||||||
|
DivisionByZero => DivisionByZero,
|
||||||
|
RemainderByZero => RemainderByZero,
|
||||||
};
|
};
|
||||||
Some(interpret::EvalError {
|
Some(interpret::EvalError {
|
||||||
kind: kind,
|
kind: kind,
|
||||||
|
|
|
@ -20,7 +20,7 @@ use rustc::middle::const_val::ConstVal;
|
||||||
use rustc::middle::region;
|
use rustc::middle::region;
|
||||||
use rustc::ty::{self, Ty};
|
use rustc::ty::{self, Ty};
|
||||||
use rustc::mir::*;
|
use rustc::mir::*;
|
||||||
use rustc::mir::interpret::{Value, PrimVal, ConstMathErr, Op};
|
use rustc::mir::interpret::{Value, PrimVal, EvalErrorKind};
|
||||||
use syntax_pos::Span;
|
use syntax_pos::Span;
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
|
@ -85,7 +85,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
this.cfg.push_assign(block, source_info, &is_min,
|
this.cfg.push_assign(block, source_info, &is_min,
|
||||||
Rvalue::BinaryOp(BinOp::Eq, arg.to_copy(), minval));
|
Rvalue::BinaryOp(BinOp::Eq, arg.to_copy(), minval));
|
||||||
|
|
||||||
let err = ConstMathErr::Overflow(Op::Neg);
|
let err = EvalErrorKind::OverflowNeg;
|
||||||
block = this.assert(block, Operand::Move(is_min), false,
|
block = this.assert(block, Operand::Move(is_min), false,
|
||||||
AssertMessage::Math(err), expr_span);
|
AssertMessage::Math(err), expr_span);
|
||||||
}
|
}
|
||||||
|
@ -310,16 +310,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
let val = result_value.clone().field(val_fld, ty);
|
let val = result_value.clone().field(val_fld, ty);
|
||||||
let of = result_value.field(of_fld, bool_ty);
|
let of = result_value.field(of_fld, bool_ty);
|
||||||
|
|
||||||
let err = ConstMathErr::Overflow(match op {
|
let err = EvalErrorKind::Overflow(op);
|
||||||
BinOp::Add => Op::Add,
|
|
||||||
BinOp::Sub => Op::Sub,
|
|
||||||
BinOp::Mul => Op::Mul,
|
|
||||||
BinOp::Shl => Op::Shl,
|
|
||||||
BinOp::Shr => Op::Shr,
|
|
||||||
_ => {
|
|
||||||
bug!("MIR build_binary_op: {:?} is not checkable", op)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
block = self.assert(block, Operand::Move(of), false,
|
block = self.assert(block, Operand::Move(of), false,
|
||||||
AssertMessage::Math(err), span);
|
AssertMessage::Math(err), span);
|
||||||
|
@ -331,11 +322,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
// and 2. there are two possible failure cases, divide-by-zero and overflow.
|
// and 2. there are two possible failure cases, divide-by-zero and overflow.
|
||||||
|
|
||||||
let (zero_err, overflow_err) = if op == BinOp::Div {
|
let (zero_err, overflow_err) = if op == BinOp::Div {
|
||||||
(ConstMathErr::DivisionByZero,
|
(EvalErrorKind::DivisionByZero,
|
||||||
ConstMathErr::Overflow(Op::Div))
|
EvalErrorKind::Overflow(op))
|
||||||
} else {
|
} else {
|
||||||
(ConstMathErr::RemainderByZero,
|
(EvalErrorKind::RemainderByZero,
|
||||||
ConstMathErr::Overflow(Op::Rem))
|
EvalErrorKind::Overflow(op))
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check for / 0
|
// Check for / 0
|
||||||
|
|
|
@ -513,7 +513,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
|
||||||
// it emits in debug mode) is performance, but it doesn't cost us any performance in miri.
|
// it emits in debug mode) is performance, but it doesn't cost us any performance in miri.
|
||||||
// If, however, the compiler ever starts transforming unchecked intrinsics into unchecked binops,
|
// If, however, the compiler ever starts transforming unchecked intrinsics into unchecked binops,
|
||||||
// we have to go back to just ignoring the overflow here.
|
// we have to go back to just ignoring the overflow here.
|
||||||
return err!(OverflowingMath);
|
return err!(Overflow(bin_op));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -269,7 +269,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
||||||
(Neg, ty::TyFloat(FloatTy::F32)) => Single::to_bits(-Single::from_bits(bytes)),
|
(Neg, ty::TyFloat(FloatTy::F32)) => Single::to_bits(-Single::from_bits(bytes)),
|
||||||
(Neg, ty::TyFloat(FloatTy::F64)) => Double::to_bits(-Double::from_bits(bytes)),
|
(Neg, ty::TyFloat(FloatTy::F64)) => Double::to_bits(-Double::from_bits(bytes)),
|
||||||
|
|
||||||
(Neg, _) if bytes == (1 << (size - 1)) => return err!(OverflowingMath),
|
(Neg, _) if bytes == (1 << (size - 1)) => return err!(OverflowNeg),
|
||||||
(Neg, _) => (-(bytes as i128)) as u128,
|
(Neg, _) => (-(bytes as i128)) as u128,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -160,9 +160,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
||||||
.to_u64()?;
|
.to_u64()?;
|
||||||
err!(ArrayIndexOutOfBounds(span, len, index))
|
err!(ArrayIndexOutOfBounds(span, len, index))
|
||||||
}
|
}
|
||||||
Math(ref err) => {
|
Math(ref err) => Err(err.clone().into()),
|
||||||
err!(Math(terminator.source_info.span, err.clone()))
|
|
||||||
}
|
|
||||||
GeneratorResumedAfterReturn |
|
GeneratorResumedAfterReturn |
|
||||||
GeneratorResumedAfterPanic => unimplemented!(),
|
GeneratorResumedAfterPanic => unimplemented!(),
|
||||||
};
|
};
|
||||||
|
|
|
@ -328,7 +328,7 @@ impl<'b, 'a, 'tcx:'b> ConstPropagator<'b, 'a, 'tcx> {
|
||||||
} else {
|
} else {
|
||||||
if overflow {
|
if overflow {
|
||||||
use rustc::mir::interpret::EvalErrorKind;
|
use rustc::mir::interpret::EvalErrorKind;
|
||||||
let mut err = EvalErrorKind::OverflowingMath.into();
|
let mut err = EvalErrorKind::Overflow(op).into();
|
||||||
ecx.report(&mut err, false, Some(span));
|
ecx.report(&mut err, false, Some(span));
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
|
@ -311,10 +311,9 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
// checked operation, just a comparison with the minimum
|
// checked operation, just a comparison with the minimum
|
||||||
// value, so we have to check for the assert message.
|
// value, so we have to check for the assert message.
|
||||||
if !bx.cx.check_overflow {
|
if !bx.cx.check_overflow {
|
||||||
use rustc::mir::interpret::ConstMathErr::Overflow;
|
use rustc::mir::interpret::EvalErrorKind::OverflowNeg;
|
||||||
use rustc::mir::interpret::Op::Neg;
|
|
||||||
|
|
||||||
if let mir::AssertMessage::Math(Overflow(Neg)) = *msg {
|
if let mir::AssertMessage::Math(OverflowNeg) = *msg {
|
||||||
const_cond = Some(expected);
|
const_cond = Some(expected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue