Add miri errors to the const eval error enum

This commit is contained in:
Oliver Schneider 2018-01-16 09:13:50 +01:00
parent 38b5ddd39b
commit c0574c054c
No known key found for this signature in database
GPG Key ID: A69F8D225B3AD7D9
4 changed files with 294 additions and 12 deletions

View File

@ -470,6 +470,7 @@ for ::middle::const_val::ErrKind<'gcx> {
ErroneousReferencedConstant(ref const_val) => {
const_val.hash_stable(hcx, hasher);
}
Miri(ref err) => err.hash_stable(hcx, hasher),
}
}
}
@ -483,6 +484,175 @@ impl_stable_hash_for!(struct ty::GenericPredicates<'tcx> {
predicates
});
impl<'gcx> HashStable<StableHashingContext<'gcx>>
for ::mir::interpret::EvalError<'gcx> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'gcx>,
hasher: &mut StableHasher<W>) {
use mir::interpret::EvalErrorKind::*;
mem::discriminant(&self.kind).hash_stable(hcx, hasher);
match self.kind {
DanglingPointerDeref |
DoubleFree |
InvalidMemoryAccess |
InvalidFunctionPointer |
InvalidBool |
InvalidDiscriminant |
InvalidNullPointerUsage |
ReadPointerAsBytes |
ReadBytesAsPointer |
InvalidPointerMath |
ReadUndefBytes |
DeadLocal |
ExecutionTimeLimitReached |
StackFrameLimitReached |
OutOfTls |
TlsOutOfBounds |
CalledClosureAsFunction |
VtableForArgumentlessMethod |
ModifiedConstantMemory |
AssumptionNotHeld |
InlineAsm |
ReallocateNonBasePtr |
DeallocateNonBasePtr |
HeapAllocZeroBytes |
Unreachable |
Panic |
ReadFromReturnPointer |
UnimplementedTraitSelection |
TypeckError |
DerefFunctionPointer |
ExecuteMemory |
OverflowingMath => {}
MachineError(ref err) => err.hash_stable(hcx, hasher),
FunctionPointerTyMismatch(a, b) => {
a.hash_stable(hcx, hasher);
b.hash_stable(hcx, hasher)
},
NoMirFor(ref s) => s.hash_stable(hcx, hasher),
UnterminatedCString(ptr) => ptr.hash_stable(hcx, hasher),
PointerOutOfBounds {
ptr,
access,
allocation_size,
} => {
ptr.hash_stable(hcx, hasher);
access.hash_stable(hcx, hasher);
allocation_size.hash_stable(hcx, hasher)
},
InvalidBoolOp(bop) => bop.hash_stable(hcx, hasher),
Unimplemented(ref s) => s.hash_stable(hcx, hasher),
ArrayIndexOutOfBounds(sp, a, b) => {
sp.hash_stable(hcx, hasher);
a.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),
InvalidChar(c) => c.hash_stable(hcx, hasher),
OutOfMemory {
allocation_size,
memory_size,
memory_usage,
} => {
allocation_size.hash_stable(hcx, hasher);
memory_size.hash_stable(hcx, hasher);
memory_usage.hash_stable(hcx, hasher)
},
AbiViolation(ref s) => s.hash_stable(hcx, hasher),
AlignmentCheckFailed {
required,
has,
} => {
required.hash_stable(hcx, hasher);
has.hash_stable(hcx, hasher)
},
MemoryLockViolation {
ptr,
len,
frame,
access,
ref lock,
} => {
ptr.hash_stable(hcx, hasher);
len.hash_stable(hcx, hasher);
frame.hash_stable(hcx, hasher);
access.hash_stable(hcx, hasher);
lock.hash_stable(hcx, hasher)
},
MemoryAcquireConflict {
ptr,
len,
kind,
ref lock,
} => {
ptr.hash_stable(hcx, hasher);
len.hash_stable(hcx, hasher);
kind.hash_stable(hcx, hasher);
lock.hash_stable(hcx, hasher)
},
InvalidMemoryLockRelease {
ptr,
len,
frame,
ref lock,
} => {
ptr.hash_stable(hcx, hasher);
len.hash_stable(hcx, hasher);
frame.hash_stable(hcx, hasher);
lock.hash_stable(hcx, hasher)
},
DeallocatedLockedMemory {
ptr,
ref lock,
} => {
ptr.hash_stable(hcx, hasher);
lock.hash_stable(hcx, hasher)
},
ValidationFailure(ref s) => s.hash_stable(hcx, hasher),
TypeNotPrimitive(ty) => ty.hash_stable(hcx, hasher),
ReallocatedWrongMemoryKind(ref a, ref b) => {
a.hash_stable(hcx, hasher);
b.hash_stable(hcx, hasher)
},
DeallocatedWrongMemoryKind(ref a, ref b) => {
a.hash_stable(hcx, hasher);
b.hash_stable(hcx, hasher)
},
IncorrectAllocationInformation(a, b, c, d) => {
a.hash_stable(hcx, hasher);
b.hash_stable(hcx, hasher);
c.hash_stable(hcx, hasher);
d.hash_stable(hcx, hasher)
},
Layout(lay) => lay.hash_stable(hcx, hasher),
HeapAllocNonPowerOfTwoAlignment(n) => n.hash_stable(hcx, hasher),
PathNotFound(ref v) => v.hash_stable(hcx, hasher),
}
}
}
impl_stable_hash_for!(enum mir::interpret::Lock {
NoLock,
WriteLock(dl),
ReadLock(v)
});
impl_stable_hash_for!(struct mir::interpret::DynamicLifetime {
frame,
region
});
impl_stable_hash_for!(enum mir::interpret::AccessKind {
Read,
Write
});
impl_stable_hash_for!(enum ty::Variance {
Covariant,
Invariant,

View File

@ -111,6 +111,13 @@ pub enum ErrKind<'tcx> {
TypeckError,
CheckMatchError,
Miri(::mir::interpret::EvalError<'tcx>),
}
impl<'tcx> From<::mir::interpret::EvalError<'tcx>> for ErrKind<'tcx> {
fn from(err: ::mir::interpret::EvalError<'tcx>) -> ErrKind<'tcx> {
ErrKind::Miri(err)
}
}
impl<'tcx> From<ConstMathErr> for ErrKind<'tcx> {
@ -173,6 +180,7 @@ impl<'a, 'gcx, 'tcx> ConstEvalErr<'tcx> {
TypeckError => simple!("type-checking failed"),
CheckMatchError => simple!("match-checking failed"),
Miri(ref err) => simple!("miri failed: {}", err),
}
}

View File

@ -12,7 +12,7 @@ use rustc_const_math::ConstMathErr;
use syntax::codemap::Span;
use backtrace::Backtrace;
#[derive(Debug)]
#[derive(Debug, Clone)]
pub struct EvalError<'tcx> {
pub kind: EvalErrorKind<'tcx>,
pub backtrace: Option<Backtrace>,
@ -31,11 +31,11 @@ impl<'tcx> From<EvalErrorKind<'tcx>> for EvalError<'tcx> {
}
}
#[derive(Debug)]
#[derive(Debug, Clone)]
pub enum EvalErrorKind<'tcx> {
/// This variant is used by machines to signal their own errors that do not
/// match an existing variant
MachineError(Box<dyn Error>),
MachineError(String),
FunctionPointerTyMismatch(FnSig<'tcx>, FnSig<'tcx>),
NoMirFor(String),
UnterminatedCString(MemoryPointer),
@ -132,7 +132,7 @@ impl<'tcx> Error for EvalError<'tcx> {
fn description(&self) -> &str {
use self::EvalErrorKind::*;
match self.kind {
MachineError(ref inner) => inner.description(),
MachineError(ref inner) => inner,
FunctionPointerTyMismatch(..) =>
"tried to call a function through a function pointer of a different type",
InvalidMemoryAccess =>
@ -247,14 +247,6 @@ impl<'tcx> Error for EvalError<'tcx> {
"encountered constants with type errors, stopping evaluation",
}
}
fn cause(&self) -> Option<&dyn Error> {
use self::EvalErrorKind::*;
match self.kind {
MachineError(ref inner) => Some(&**inner),
_ => None,
}
}
}
impl<'tcx> fmt::Display for EvalError<'tcx> {

View File

@ -18,6 +18,7 @@ use ty::{self, Lift, Ty, TyCtxt};
use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
use rustc_data_structures::accumulate_vec::AccumulateVec;
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
use mir::interpret;
use std::rc::Rc;
@ -585,6 +586,116 @@ impl<'a, 'tcx> Lift<'tcx> for ConstEvalErr<'a> {
}
}
impl<'a, 'tcx> Lift<'tcx> for interpret::EvalError<'a> {
type Lifted = interpret::EvalError<'tcx>;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
use mir::interpret::EvalErrorKind::*;
let kind = match self.kind {
MachineError(ref err) => MachineError(err.clone()),
FunctionPointerTyMismatch(a, b) => FunctionPointerTyMismatch(
tcx.lift(&a)?,
tcx.lift(&b)?,
),
NoMirFor(ref s) => NoMirFor(s.clone()),
UnterminatedCString(ptr) => UnterminatedCString(ptr),
DanglingPointerDeref => DanglingPointerDeref,
DoubleFree => DoubleFree,
InvalidMemoryAccess => InvalidMemoryAccess,
InvalidFunctionPointer => InvalidFunctionPointer,
InvalidBool => InvalidBool,
InvalidDiscriminant => InvalidDiscriminant,
PointerOutOfBounds {
ptr,
access,
allocation_size,
} => PointerOutOfBounds { ptr, access, allocation_size },
InvalidNullPointerUsage => InvalidNullPointerUsage,
ReadPointerAsBytes => ReadPointerAsBytes,
ReadBytesAsPointer => ReadBytesAsPointer,
InvalidPointerMath => InvalidPointerMath,
ReadUndefBytes => ReadUndefBytes,
DeadLocal => DeadLocal,
InvalidBoolOp(bop) => InvalidBoolOp(bop),
Unimplemented(ref s) => Unimplemented(s.clone()),
DerefFunctionPointer => DerefFunctionPointer,
ExecuteMemory => ExecuteMemory,
ArrayIndexOutOfBounds(sp, a, b) => ArrayIndexOutOfBounds(sp, a, b),
Math(sp, ref err) => Math(sp, err.clone()),
Intrinsic(ref s) => Intrinsic(s.clone()),
OverflowingMath => OverflowingMath,
InvalidChar(c) => InvalidChar(c),
OutOfMemory {
allocation_size,
memory_size,
memory_usage,
} => OutOfMemory { allocation_size, memory_size, memory_usage },
ExecutionTimeLimitReached => ExecutionTimeLimitReached,
StackFrameLimitReached => StackFrameLimitReached,
OutOfTls => OutOfTls,
TlsOutOfBounds => TlsOutOfBounds,
AbiViolation(ref s) => AbiViolation(s.clone()),
AlignmentCheckFailed {
required,
has,
} => AlignmentCheckFailed { required, has },
MemoryLockViolation {
ptr,
len,
frame,
access,
ref lock,
} => MemoryLockViolation { ptr, len, frame, access, lock: lock.clone() },
MemoryAcquireConflict {
ptr,
len,
kind,
ref lock,
} => MemoryAcquireConflict { ptr, len, kind, lock: lock.clone() },
InvalidMemoryLockRelease {
ptr,
len,
frame,
ref lock,
} => InvalidMemoryLockRelease { ptr, len, frame, lock: lock.clone() },
DeallocatedLockedMemory {
ptr,
ref lock,
} => DeallocatedLockedMemory { ptr, lock: lock.clone() },
ValidationFailure(ref s) => ValidationFailure(s.clone()),
CalledClosureAsFunction => CalledClosureAsFunction,
VtableForArgumentlessMethod => VtableForArgumentlessMethod,
ModifiedConstantMemory => ModifiedConstantMemory,
AssumptionNotHeld => AssumptionNotHeld,
InlineAsm => InlineAsm,
TypeNotPrimitive(ty) => TypeNotPrimitive(tcx.lift(&ty)?),
ReallocatedWrongMemoryKind(ref a, ref b) => {
ReallocatedWrongMemoryKind(a.clone(), b.clone())
},
DeallocatedWrongMemoryKind(ref a, ref b) => {
DeallocatedWrongMemoryKind(a.clone(), b.clone())
},
ReallocateNonBasePtr => ReallocateNonBasePtr,
DeallocateNonBasePtr => DeallocateNonBasePtr,
IncorrectAllocationInformation(a, b, c, d) => {
IncorrectAllocationInformation(a, b, c, d)
},
Layout(lay) => Layout(tcx.lift(&lay)?),
HeapAllocZeroBytes => HeapAllocZeroBytes,
HeapAllocNonPowerOfTwoAlignment(n) => HeapAllocNonPowerOfTwoAlignment(n),
Unreachable => Unreachable,
Panic => Panic,
ReadFromReturnPointer => ReadFromReturnPointer,
PathNotFound(ref v) => PathNotFound(v.clone()),
UnimplementedTraitSelection => UnimplementedTraitSelection,
TypeckError => TypeckError,
};
Some(interpret::EvalError {
kind,
backtrace: self.backtrace.clone(),
})
}
}
impl<'a, 'tcx> Lift<'tcx> for const_val::ErrKind<'a> {
type Lifted = const_val::ErrKind<'tcx>;
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
@ -614,6 +725,7 @@ impl<'a, 'tcx> Lift<'tcx> for const_val::ErrKind<'a> {
TypeckError => TypeckError,
CheckMatchError => CheckMatchError,
Miri(ref e) => return tcx.lift(e).map(Miri),
})
}
}