fixing fallout due to InterpError refactor

This commit is contained in:
Saleem Jaffer 2019-07-27 17:49:12 +05:30
parent 4f0ab6ccce
commit 307798aa38
21 changed files with 259 additions and 266 deletions

View File

@ -4,6 +4,7 @@ use super::{
Pointer, InterpResult, AllocId, ScalarMaybeUndef, write_target_uint, read_target_uint, Scalar,
};
use super::error::UnsupportedInfo::*;
use crate::ty::layout::{Size, Align};
use syntax::ast::Mutability;
use std::iter;
@ -244,7 +245,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
Ok(&self.get_bytes(cx, ptr, size_with_null)?[..size])
}
// This includes the case where `offset` is out-of-bounds to begin with.
None => err!(UnterminatedCString(ptr.erase_tag())),
None => err!(Unsupported(UnterminatedCString(ptr.erase_tag()))),
}
}
@ -446,7 +447,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation<Tag, Extra> {
if self.relocations(cx, ptr, size).is_empty() {
Ok(())
} else {
err!(ReadPointerAsBytes)
err!(Unsupported(ReadPointerAsBytes))
}
}
@ -516,7 +517,7 @@ impl<'tcx, Tag, Extra> Allocation<Tag, Extra> {
self.undef_mask.is_range_defined(
ptr.offset,
ptr.offset + size,
).or_else(|idx| err!(ReadUndefBytes(idx)))
).or_else(|idx| err!(Unsupported(ReadUndefBytes(idx))))
}
pub fn mark_definedness(

View File

@ -142,7 +142,7 @@ impl<'tcx> ConstEvalErr<'tcx> {
InterpError::InvalidProgram(Layout(LayoutError::Unknown(_))) |
InterpError::InvalidProgram(TooGeneric) =>
return Err(ErrorHandled::TooGeneric),
InterpError::Layout(LayoutError::SizeOverflow(_)) |
InterpError::InvalidProgram(Layout(LayoutError::SizeOverflow(_))) |
InterpError::InvalidProgram(TypeckError) =>
return Err(ErrorHandled::Reported),
_ => {},
@ -325,16 +325,47 @@ pub enum InvalidProgramInfo<'tcx> {
Layout(layout::LayoutError<'tcx>),
}
impl fmt::Debug for InvalidProgramInfo<'tcx> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use InvalidProgramInfo::*;
match self {
TooGeneric =>
write!(f, "encountered overly generic constant"),
ReferencedConstant =>
write!(f, "referenced constant has errors"),
TypeckError =>
write!(f, "encountered constants with type errors, stopping evaluation"),
Layout(ref err) =>
write!(f, "rustc layout computation failed: {:?}", err),
}
}
}
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
pub enum UndefinedBehaviourInfo {
/// Handle cases which for which we do not have a fixed variant
/// Handle cases which for which we do not have a fixed variant.
Ub(String),
/// Unreachable code was executed.
Unreachable,
}
impl fmt::Debug for UndefinedBehaviourInfo {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use UndefinedBehaviourInfo::*;
match self {
Ub(ref msg) =>
write!(f, "{}", msg),
Unreachable =>
write!(f, "entered unreachable code"),
}
}
}
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
pub enum UnsupportedInfo<'tcx> {
Unimplemented(String),
// -- Everything below is not classified yet --
FunctionAbiMismatch(Abi, Abi),
FunctionArgMismatch(Ty<'tcx>, Ty<'tcx>),
FunctionRetMismatch(Ty<'tcx>, Ty<'tcx>),
@ -400,6 +431,19 @@ pub enum ResourceExhaustionInfo {
InfiniteLoop,
}
impl fmt::Debug for ResourceExhaustionInfo {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use ResourceExhaustionInfo::*;
match self {
StackFrameLimitReached =>
write!(f, "reached the configured maximum number of stack frames"),
InfiniteLoop =>
write!(f, "duplicate interpreter state observed here, const evaluation will never \
terminate"),
}
}
}
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
pub enum InterpError<'tcx> {
/// The program panicked.
@ -431,139 +475,131 @@ impl fmt::Display for InterpError<'_> {
impl fmt::Debug for InterpError<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use InterpError::*;
use UnsupportedInfo::*;
match *self {
PointerOutOfBounds { ptr, msg, allocation_size } => {
Unsupported(PointerOutOfBounds { ptr, msg, allocation_size }) => {
write!(f, "{} failed: pointer must be in-bounds at offset {}, \
but is outside bounds of allocation {} which has size {}",
msg, ptr.offset.bytes(), ptr.alloc_id, allocation_size.bytes())
},
ValidationFailure(ref err) => {
Unsupported(ValidationFailure(ref err)) => {
write!(f, "type validation failed: {}", err)
}
NoMirFor(ref func) => write!(f, "no mir for `{}`", func),
FunctionAbiMismatch(caller_abi, callee_abi) =>
Unsupported(NoMirFor(ref func)) => write!(f, "no mir for `{}`", func),
Unsupported(FunctionAbiMismatch(caller_abi, callee_abi)) =>
write!(f, "tried to call a function with ABI {:?} using caller ABI {:?}",
callee_abi, caller_abi),
FunctionArgMismatch(caller_ty, callee_ty) =>
Unsupported(FunctionArgMismatch(caller_ty, callee_ty)) =>
write!(f, "tried to call a function with argument of type {:?} \
passing data of type {:?}",
callee_ty, caller_ty),
FunctionRetMismatch(caller_ty, callee_ty) =>
Unsupported(FunctionRetMismatch(caller_ty, callee_ty)) =>
write!(f, "tried to call a function with return type {:?} \
passing return place of type {:?}",
callee_ty, caller_ty),
FunctionArgCountMismatch =>
Unsupported(FunctionArgCountMismatch) =>
write!(f, "tried to call a function with incorrect number of arguments"),
ReallocatedWrongMemoryKind(ref old, ref new) =>
Unsupported(ReallocatedWrongMemoryKind(ref old, ref new)) =>
write!(f, "tried to reallocate memory from {} to {}", old, new),
DeallocatedWrongMemoryKind(ref old, ref new) =>
Unsupported(DeallocatedWrongMemoryKind(ref old, ref new)) =>
write!(f, "tried to deallocate {} memory but gave {} as the kind", old, new),
InvalidChar(c) =>
Unsupported(InvalidChar(c)) =>
write!(f, "tried to interpret an invalid 32-bit value as a char: {}", c),
AlignmentCheckFailed { required, has } =>
Unsupported(AlignmentCheckFailed { required, has }) =>
write!(f, "tried to access memory with alignment {}, but alignment {} is required",
has.bytes(), required.bytes()),
TypeNotPrimitive(ty) =>
Unsupported(TypeNotPrimitive(ty)) =>
write!(f, "expected primitive type, got {}", ty),
Layout(ref err) =>
write!(f, "rustc layout computation failed: {:?}", err),
PathNotFound(ref path) =>
Unsupported(PathNotFound(ref path)) =>
write!(f, "Cannot find path {:?}", path),
IncorrectAllocationInformation(size, size2, align, align2) =>
Unsupported(IncorrectAllocationInformation(size, size2, align, align2)) =>
write!(f, "incorrect alloc info: expected size {} and align {}, \
got size {} and align {}",
size.bytes(), align.bytes(), size2.bytes(), align2.bytes()),
InvalidDiscriminant(val) =>
Unsupported(InvalidDiscriminant(val)) =>
write!(f, "encountered invalid enum discriminant {}", val),
Exit(code) =>
write!(f, "exited with status code {}", code),
InvalidMemoryAccess =>
Unsupported(InvalidMemoryAccess) =>
write!(f, "tried to access memory through an invalid pointer"),
DanglingPointerDeref =>
Unsupported(DanglingPointerDeref) =>
write!(f, "dangling pointer was dereferenced"),
DoubleFree =>
Unsupported(DoubleFree) =>
write!(f, "tried to deallocate dangling pointer"),
InvalidFunctionPointer =>
Unsupported(InvalidFunctionPointer) =>
write!(f, "tried to use a function pointer after offsetting it"),
InvalidBool =>
Unsupported(InvalidBool) =>
write!(f, "invalid boolean value read"),
InvalidNullPointerUsage =>
Unsupported(InvalidNullPointerUsage) =>
write!(f, "invalid use of NULL pointer"),
ReadPointerAsBytes =>
Unsupported(ReadPointerAsBytes) =>
write!(f, "a raw memory access tried to access part of a pointer value as raw \
bytes"),
ReadBytesAsPointer =>
Unsupported(ReadBytesAsPointer) =>
write!(f, "a memory access tried to interpret some bytes as a pointer"),
ReadForeignStatic =>
Unsupported(ReadForeignStatic) =>
write!(f, "tried to read from foreign (extern) static"),
InvalidPointerMath =>
Unsupported(InvalidPointerMath) =>
write!(f, "attempted to do invalid arithmetic on pointers that would leak base \
addresses, e.g., comparing pointers into different allocations"),
DeadLocal =>
Unsupported(DeadLocal) =>
write!(f, "tried to access a dead local variable"),
DerefFunctionPointer =>
Unsupported(DerefFunctionPointer) =>
write!(f, "tried to dereference a function pointer"),
ExecuteMemory =>
Unsupported(ExecuteMemory) =>
write!(f, "tried to treat a memory pointer as a function pointer"),
StackFrameLimitReached =>
write!(f, "reached the configured maximum number of stack frames"),
OutOfTls =>
Unsupported(OutOfTls) =>
write!(f, "reached the maximum number of representable TLS keys"),
TlsOutOfBounds =>
Unsupported(TlsOutOfBounds) =>
write!(f, "accessed an invalid (unallocated) TLS key"),
CalledClosureAsFunction =>
Unsupported(CalledClosureAsFunction) =>
write!(f, "tried to call a closure through a function pointer"),
VtableForArgumentlessMethod =>
Unsupported(VtableForArgumentlessMethod) =>
write!(f, "tried to call a vtable function without arguments"),
ModifiedConstantMemory =>
Unsupported(ModifiedConstantMemory) =>
write!(f, "tried to modify constant memory"),
ModifiedStatic =>
Unsupported(ModifiedStatic) =>
write!(f, "tried to modify a static's initial value from another static's \
initializer"),
AssumptionNotHeld =>
Unsupported(AssumptionNotHeld) =>
write!(f, "`assume` argument was false"),
InlineAsm =>
Unsupported(InlineAsm) =>
write!(f, "miri does not support inline assembly"),
ReallocateNonBasePtr =>
Unsupported(ReallocateNonBasePtr) =>
write!(f, "tried to reallocate with a pointer not to the beginning of an \
existing object"),
DeallocateNonBasePtr =>
Unsupported(DeallocateNonBasePtr) =>
write!(f, "tried to deallocate with a pointer not to the beginning of an \
existing object"),
HeapAllocZeroBytes =>
Unsupported(HeapAllocZeroBytes) =>
write!(f, "tried to re-, de- or allocate zero bytes on the heap"),
Unreachable =>
write!(f, "entered unreachable code"),
ReadFromReturnPointer =>
Unsupported(ReadFromReturnPointer) =>
write!(f, "tried to read from the return pointer"),
UnimplementedTraitSelection =>
Unsupported(UnimplementedTraitSelection) =>
write!(f, "there were unresolved type arguments during trait selection"),
TypeckError =>
write!(f, "encountered constants with type errors, stopping evaluation"),
TooGeneric =>
write!(f, "encountered overly generic constant"),
ReferencedConstant =>
write!(f, "referenced constant has errors"),
InfiniteLoop =>
write!(f, "duplicate interpreter state observed here, const evaluation will never \
terminate"),
InvalidBoolOp(_) =>
Unsupported(InvalidBoolOp(_)) =>
write!(f, "invalid boolean operation"),
UnterminatedCString(_) =>
Unsupported(UnterminatedCString(_)) =>
write!(f, "attempted to get length of a null terminated string, but no null \
found before end of allocation"),
ReadUndefBytes(_) =>
Unsupported(ReadUndefBytes(_)) =>
write!(f, "attempted to read undefined bytes"),
HeapAllocNonPowerOfTwoAlignment(_) =>
Unsupported(HeapAllocNonPowerOfTwoAlignment(_)) =>
write!(f, "tried to re-, de-, or allocate heap memory with alignment that is \
not a power of two"),
MachineError(ref msg) |
Unimplemented(ref msg) |
AbiViolation(ref msg) |
Intrinsic(ref msg) =>
Unsupported(MachineError(ref msg)) |
Unsupported(Unimplemented(ref msg)) |
Unsupported(AbiViolation(ref msg)) |
Unsupported(Intrinsic(ref msg)) =>
write!(f, "{}", msg),
InvalidProgram(ref msg) =>
write!(f, "{:?}", msg),
UndefinedBehaviour(ref msg) =>
write!(f, "{:?}", msg),
ResourceExhaustion(ref msg) =>
write!(f, "{:?}", msg),
Panic(ref msg) =>
write!(f, "{:?}", msg),
Exit(code) =>
write!(f, "exited with status code {}", code),
}
}
}

View File

@ -12,7 +12,8 @@ mod pointer;
pub use self::error::{
InterpErrorInfo, InterpResult, InterpError, AssertMessage, ConstEvalErr, struct_error,
FrameInfo, ConstEvalRawResult, ConstEvalResult, ErrorHandled, PanicMessage
FrameInfo, ConstEvalRawResult, ConstEvalResult, ErrorHandled, PanicMessage, UnsupportedInfo,
InvalidProgramInfo, ResourceExhaustionInfo, UndefinedBehaviourInfo,
};
pub use self::value::{Scalar, ScalarMaybeUndef, RawConst, ConstValue};

View File

@ -1,5 +1,6 @@
use std::fmt::{self, Display};
use super::error::UnsupportedInfo::*;
use crate::mir;
use crate::ty::layout::{self, HasDataLayout, Size};
use rustc_macros::HashStable;
@ -198,11 +199,11 @@ impl<'tcx, Tag> Pointer<Tag> {
msg: CheckInAllocMsg,
) -> InterpResult<'tcx, ()> {
if self.offset > allocation_size {
err!(PointerOutOfBounds {
err!(Unsupported(PointerOutOfBounds {
ptr: self.erase_tag(),
msg,
allocation_size,
})
}))
} else {
Ok(())
}

View File

@ -2,6 +2,7 @@ use std::fmt;
use rustc_macros::HashStable;
use rustc_apfloat::{Float, ieee::{Double, Single}};
use super::error::UnsupportedInfo::*;
use crate::ty::{Ty, InferConst, ParamConst, layout::{HasDataLayout, Size, Align}, subst::SubstsRef};
use crate::ty::PlaceholderConst;
use crate::hir::def_id::DefId;
@ -360,7 +361,7 @@ impl<'tcx, Tag> Scalar<Tag> {
Scalar::check_data(data, size);
Ok(data)
}
Scalar::Ptr(_) => err!(ReadPointerAsBytes),
Scalar::Ptr(_) => err!(Unsupported(ReadPointerAsBytes)),
}
}
@ -373,8 +374,8 @@ impl<'tcx, Tag> Scalar<Tag> {
#[inline]
pub fn to_ptr(self) -> InterpResult<'tcx, Pointer<Tag>> {
match self {
Scalar::Raw { data: 0, .. } => err!(InvalidNullPointerUsage),
Scalar::Raw { .. } => err!(ReadBytesAsPointer),
Scalar::Raw { data: 0, .. } => err!(Unsupported(InvalidNullPointerUsage)),
Scalar::Raw { .. } => err!(Unsupported(ReadBytesAsPointer)),
Scalar::Ptr(p) => Ok(p),
}
}
@ -406,7 +407,7 @@ impl<'tcx, Tag> Scalar<Tag> {
match self {
Scalar::Raw { data: 0, size: 1 } => Ok(false),
Scalar::Raw { data: 1, size: 1 } => Ok(true),
_ => err!(InvalidBool),
_ => err!(Unsupported(InvalidBool)),
}
}
@ -414,7 +415,7 @@ impl<'tcx, Tag> Scalar<Tag> {
let val = self.to_u32()?;
match ::std::char::from_u32(val) {
Some(c) => Ok(c),
None => err!(InvalidChar(val as u128)),
None => err!(Unsupported(InvalidChar(val as u128))),
}
}
@ -537,7 +538,7 @@ impl<'tcx, Tag> ScalarMaybeUndef<Tag> {
pub fn not_undef(self) -> InterpResult<'static, Scalar<Tag>> {
match self {
ScalarMaybeUndef::Scalar(scalar) => Ok(scalar),
ScalarMaybeUndef::Undef => err!(ReadUndefBytes(Size::from_bytes(0))),
ScalarMaybeUndef::Undef => err!(Unsupported(ReadUndefBytes(Size::from_bytes(0)))),
}
}

View File

@ -24,7 +24,8 @@ use crate::interpret::{self,
RawConst, ConstValue,
InterpResult, InterpErrorInfo, InterpError, GlobalId, InterpCx, StackPopCleanup,
Allocation, AllocId, MemoryKind,
snapshot, RefTracking, intern_const_alloc_recursive,
snapshot, RefTracking, intern_const_alloc_recursive, UnsupportedInfo::*,
InvalidProgramInfo::*,
};
/// Number of steps until the detector even starts doing anything.
@ -183,7 +184,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
impl<'tcx> Into<InterpErrorInfo<'tcx>> for ConstEvalError {
fn into(self) -> InterpErrorInfo<'tcx> {
InterpError::MachineError(self.to_string()).into()
InterpError::Unsupported(MachineError(self.to_string())).into()
}
}
@ -352,7 +353,9 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
ecx.goto_block(ret)?; // fully evaluated and done
Ok(None)
} else {
err!(MachineError(format!("calling non-const function `{}`", instance)))
err!(Unsupported(
MachineError(format!("calling non-const function `{}`", instance))
))
};
}
}
@ -360,7 +363,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
Ok(Some(match ecx.load_mir(instance.def) {
Ok(body) => body,
Err(err) => {
if let InterpError::NoMirFor(ref path) = err.kind {
if let InterpError::Unsupported(NoMirFor(ref path)) = err.kind {
return Err(
ConstEvalError::NeedsRfc(format!("calling extern function `{}`", path))
.into(),
@ -412,7 +415,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
_tcx: TyCtxt<'tcx>,
_def_id: DefId,
) -> InterpResult<'tcx, Cow<'tcx, Allocation<Self::PointerTag>>> {
err!(ReadForeignStatic)
err!(Unsupported(ReadForeignStatic))
}
#[inline(always)]
@ -698,7 +701,7 @@ pub fn const_eval_raw_provider<'tcx>(
// any other kind of error will be reported to the user as a deny-by-default lint
_ => if let Some(p) = cid.promoted {
let span = tcx.promoted_mir(def_id)[p].span;
if let InterpError::ReferencedConstant = err.error {
if let InterpError::InvalidProgram(ReferencedConstant) = err.error {
err.report_as_error(
tcx.at(span),
"evaluation of constant expression failed",

View File

@ -9,7 +9,8 @@ use rustc_apfloat::{Float, FloatConvert};
use rustc::mir::interpret::{
Scalar, InterpResult, Pointer, PointerArithmetic, InterpError,
};
use rustc::mir::CastKind;
use rustc::mir::{CastKind, interpret::{UnsupportedInfo::*, InvalidProgramInfo::*}};
use super::{InterpCx, Machine, PlaceTy, OpTy, Immediate, FnVal};
@ -85,7 +86,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
self.param_env,
def_id,
substs,
).ok_or_else(|| InterpError::TooGeneric.into());
).ok_or_else(|| InterpError::InvalidProgram(TooGeneric).into());
let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance?));
self.write_scalar(Scalar::Ptr(fn_ptr.into()), dest)?;
}
@ -199,7 +200,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
},
// Casts to bool are not permitted by rustc, no need to handle them here.
_ => err!(Unimplemented(format!("int to {:?} cast", dest_layout.ty))),
_ => err!(Unsupported(Unimplemented(format!("int to {:?} cast", dest_layout.ty)))),
}
}

View File

@ -17,7 +17,8 @@ use rustc::mir::interpret::{
ErrorHandled,
GlobalId, Scalar, Pointer, FrameInfo, AllocId,
InterpResult, InterpError,
truncate, sign_extend,
truncate, sign_extend, UnsupportedInfo::*, InvalidProgramInfo::*,
ResourceExhaustionInfo::*, UndefinedBehaviourInfo::*,
};
use rustc_data_structures::fx::FxHashMap;
@ -135,7 +136,7 @@ pub enum LocalValue<Tag=(), Id=AllocId> {
impl<'tcx, Tag: Copy + 'static> LocalState<'tcx, Tag> {
pub fn access(&self) -> InterpResult<'tcx, Operand<Tag>> {
match self.value {
LocalValue::Dead => err!(DeadLocal),
LocalValue::Dead => err!(Unsupported(DeadLocal)),
LocalValue::Uninitialized =>
bug!("The type checker should prevent reading from a never-written local"),
LocalValue::Live(val) => Ok(val),
@ -148,7 +149,7 @@ impl<'tcx, Tag: Copy + 'static> LocalState<'tcx, Tag> {
&mut self,
) -> InterpResult<'tcx, Result<&mut LocalValue<Tag>, MemPlace<Tag>>> {
match self.value {
LocalValue::Dead => err!(DeadLocal),
LocalValue::Dead => err!(Unsupported(DeadLocal)),
LocalValue::Live(Operand::Indirect(mplace)) => Ok(Err(mplace)),
ref mut local @ LocalValue::Live(Operand::Immediate(_)) |
ref mut local @ LocalValue::Uninitialized => {
@ -191,7 +192,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> LayoutOf for InterpCx<'mir, 'tcx, M> {
#[inline]
fn layout_of(&self, ty: Ty<'tcx>) -> Self::TyLayout {
self.tcx.layout_of(self.param_env.and(ty))
.map_err(|layout| InterpError::Layout(layout).into())
.map_err(|layout| InterpError::InvalidProgram(Layout(layout)).into())
}
}
@ -302,7 +303,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
&substs,
)),
None => if substs.needs_subst() {
err!(TooGeneric).into()
err!(InvalidProgram(TooGeneric)).into()
} else {
Ok(substs)
},
@ -323,7 +324,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
self.param_env,
def_id,
substs,
).ok_or_else(|| InterpError::TooGeneric.into())
).ok_or_else(|| InterpError::InvalidProgram(TooGeneric).into())
}
pub fn load_mir(
@ -336,14 +337,14 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
&& self.tcx.has_typeck_tables(did)
&& self.tcx.typeck_tables_of(did).tainted_by_errors
{
return err!(TypeckError);
return err!(InvalidProgram(TypeckError));
}
trace!("load mir {:?}", instance);
match instance {
ty::InstanceDef::Item(def_id) => if self.tcx.is_mir_available(did) {
Ok(self.tcx.optimized_mir(did))
} else {
err!(NoMirFor(self.tcx.def_path_str(def_id)))
err!(Unsupported(NoMirFor(self.tcx.def_path_str(def_id))))
},
_ => Ok(self.tcx.instance_mir(instance)),
}
@ -356,7 +357,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
match self.stack.last() {
Some(frame) => Ok(self.monomorphize_with_substs(t, frame.instance.substs)?),
None => if t.needs_subst() {
err!(TooGeneric).into()
err!(InvalidProgram(TooGeneric)).into()
} else {
Ok(t)
},
@ -373,7 +374,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let substituted = t.subst(*self.tcx, substs);
if substituted.needs_subst() {
return err!(TooGeneric);
return err!(InvalidProgram(TooGeneric));
}
Ok(self.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), substituted))
@ -572,7 +573,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
info!("ENTERING({}) {}", self.cur_frame(), self.frame().instance);
if self.stack.len() > self.tcx.sess.const_eval_stack_frame_limit {
err!(StackFrameLimitReached)
err!(ResourceExhaustion(StackFrameLimitReached))
} else {
Ok(())
}
@ -620,7 +621,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
}
} else {
// Uh, that shouldn't happen... the function did not intend to return
return err!(Unreachable);
return err!(UndefinedBehaviour(Unreachable));
}
// Jump to new block -- *after* validation so that the spans make more sense.
match frame.return_to_block {
@ -694,8 +695,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// `Memory::get_static_alloc` which has to use `const_eval_raw` to avoid cycles.
let val = self.tcx.const_eval_raw(param_env.and(gid)).map_err(|err| {
match err {
ErrorHandled::Reported => InterpError::ReferencedConstant,
ErrorHandled::TooGeneric => InterpError::TooGeneric,
ErrorHandled::Reported => InterpError::InvalidProgram(ReferencedConstant),
ErrorHandled::TooGeneric => InterpError::InvalidProgram(TooGeneric),
}
})?;
self.raw_const_to_mplace(val)

View File

@ -5,7 +5,7 @@
use rustc::ty::{Ty, TyCtxt, ParamEnv, self};
use rustc::mir::interpret::{
InterpResult, ErrorHandled,
InterpResult, ErrorHandled, UnsupportedInfo::*,
};
use rustc::hir;
use rustc::hir::def_id::DefId;
@ -293,7 +293,7 @@ pub fn intern_const_alloc_recursive(
if let Err(error) = interned {
// This can happen when e.g. the tag of an enum is not a valid discriminant. We do have
// to read enum discriminants in order to find references in enum variant fields.
if let InterpError::ValidationFailure(_) = error.kind {
if let InterpError::Unsupported(ValidationFailure(_)) = error.kind {
let err = crate::const_eval::error_to_const_error(&ecx, error);
match err.struct_error(ecx.tcx, "it is undefined behavior to use this value") {
Ok(mut diag) => {
@ -328,9 +328,9 @@ pub fn intern_const_alloc_recursive(
}
} else if ecx.memory().dead_alloc_map.contains_key(&alloc_id) {
// dangling pointer
return err!(ValidationFailure(
return err!(Unsupported(ValidationFailure(
"encountered dangling pointer in final constant".into(),
))
)))
}
}
Ok(())

View File

@ -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, PanicMessage,
InterpResult, InterpError, Scalar, PanicMessage, UnsupportedInfo::*,
};
use super::{
@ -100,11 +100,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let bits = self.read_scalar(args[0])?.to_bits(layout_of.size)?;
let kind = match layout_of.abi {
ty::layout::Abi::Scalar(ref scalar) => scalar.value,
_ => Err(::rustc::mir::interpret::InterpError::TypeNotPrimitive(ty))?,
_ => Err(InterpError::Unsupported(TypeNotPrimitive(ty)))?,
};
let out_val = if intrinsic_name.ends_with("_nonzero") {
if bits == 0 {
return err!(Intrinsic(format!("{} called on 0", intrinsic_name)));
return err!(
Unsupported(Intrinsic(format!("{} called on 0", intrinsic_name)))
);
}
numeric_intrinsic(intrinsic_name.trim_end_matches("_nonzero"), bits, kind)?
} else {
@ -190,9 +192,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
if overflowed {
let layout = self.layout_of(substs.type_at(0))?;
let r_val = r.to_scalar()?.to_bits(layout.size)?;
return err!(Intrinsic(
return err!(Unsupported(Intrinsic(
format!("Overflowing shift by {} in {}", r_val, intrinsic_name),
));
)));
}
self.write_scalar(val, dest)?;
}

View File

@ -11,7 +11,7 @@ use rustc::ty::{self, TyCtxt};
use super::{
Allocation, AllocId, InterpResult, InterpError, Scalar, AllocationExtra,
InterpCx, PlaceTy, OpTy, ImmTy, MemoryKind, Pointer, Memory,
InterpCx, PlaceTy, OpTy, ImmTy, MemoryKind, Pointer, Memory, UnsupportedInfo::*
};
/// Whether this kind of memory is allowed to leak
@ -240,9 +240,9 @@ pub trait Machine<'mir, 'tcx>: Sized {
int: u64,
) -> InterpResult<'tcx, Pointer<Self::PointerTag>> {
Err((if int == 0 {
InterpError::InvalidNullPointerUsage
InterpError::Unsupported(InvalidNullPointerUsage)
} else {
InterpError::ReadBytesAsPointer
InterpError::Unsupported(ReadBytesAsPointer)
}).into())
}
@ -251,6 +251,6 @@ pub trait Machine<'mir, 'tcx>: Sized {
_mem: &Memory<'mir, 'tcx, Self>,
_ptr: Pointer<Self::PointerTag>,
) -> InterpResult<'tcx, u64> {
err!(ReadPointerAsBytes)
err!(Unsupported(ReadPointerAsBytes))
}
}

View File

@ -19,7 +19,8 @@ use syntax::ast::Mutability;
use super::{
Pointer, AllocId, Allocation, GlobalId, AllocationExtra,
InterpResult, Scalar, InterpError, GlobalAlloc, PointerArithmetic,
Machine, AllocMap, MayLeak, ErrorHandled, CheckInAllocMsg,
Machine, AllocMap, MayLeak, ErrorHandled, CheckInAllocMsg, UnsupportedInfo::*,
InvalidProgramInfo::*
};
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
@ -66,10 +67,9 @@ impl<'tcx, Other> FnVal<'tcx, Other> {
match self {
FnVal::Instance(instance) =>
Ok(instance),
FnVal::Other(_) =>
err!(MachineError(
format!("Expected instance function pointer, got 'other' pointer")
)),
FnVal::Other(_) => err!(Unsupported(MachineError(format!(
"Expected instance function pointer, got 'other' pointer"
)))),
}
}
}
@ -203,7 +203,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
kind: MemoryKind<M::MemoryKinds>,
) -> InterpResult<'tcx, Pointer<M::PointerTag>> {
if ptr.offset.bytes() != 0 {
return err!(ReallocateNonBasePtr);
return err!(Unsupported(ReallocateNonBasePtr));
}
// For simplicities' sake, we implement reallocate as "alloc, copy, dealloc".
@ -244,7 +244,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
trace!("deallocating: {}", ptr.alloc_id);
if ptr.offset.bytes() != 0 {
return err!(DeallocateNonBasePtr);
return err!(Unsupported(DeallocateNonBasePtr));
}
let (alloc_kind, mut alloc) = match self.alloc_map.remove(&ptr.alloc_id) {
@ -252,33 +252,33 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
None => {
// Deallocating static memory -- always an error
return match self.tcx.alloc_map.lock().get(ptr.alloc_id) {
Some(GlobalAlloc::Function(..)) => err!(DeallocatedWrongMemoryKind(
Some(GlobalAlloc::Function(..)) => err!(Unsupported(DeallocatedWrongMemoryKind(
"function".to_string(),
format!("{:?}", kind),
)),
))),
Some(GlobalAlloc::Static(..)) |
Some(GlobalAlloc::Memory(..)) => err!(DeallocatedWrongMemoryKind(
Some(GlobalAlloc::Memory(..)) => err!(Unsupported(DeallocatedWrongMemoryKind(
"static".to_string(),
format!("{:?}", kind),
)),
None => err!(DoubleFree)
))),
None => err!(Unsupported(DoubleFree))
}
}
};
if alloc_kind != kind {
return err!(DeallocatedWrongMemoryKind(
return err!(Unsupported(DeallocatedWrongMemoryKind(
format!("{:?}", alloc_kind),
format!("{:?}", kind),
));
)));
}
if let Some((size, align)) = old_size_and_align {
if size.bytes() != alloc.bytes.len() as u64 || align != alloc.align {
let bytes = Size::from_bytes(alloc.bytes.len() as u64);
return err!(IncorrectAllocationInformation(size,
return err!(Unsupported(IncorrectAllocationInformation(size,
bytes,
align,
alloc.align));
alloc.align)));
}
}
@ -323,10 +323,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
} else {
// The biggest power of two through which `offset` is divisible.
let offset_pow2 = 1 << offset.trailing_zeros();
err!(AlignmentCheckFailed {
err!(Unsupported(AlignmentCheckFailed {
has: Align::from_bytes(offset_pow2).unwrap(),
required: align,
})
}))
}
}
@ -345,7 +345,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
assert!(size.bytes() == 0);
// Must be non-NULL and aligned.
if bits == 0 {
return err!(InvalidNullPointerUsage);
return err!(Unsupported(InvalidNullPointerUsage));
}
check_offset_align(bits, align)?;
None
@ -366,10 +366,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
// got picked we might be aligned even if this check fails.
// We instead have to fall back to converting to an integer and checking
// the "real" alignment.
return err!(AlignmentCheckFailed {
return err!(Unsupported(AlignmentCheckFailed {
has: alloc_align,
required: align,
});
}));
}
check_offset_align(ptr.offset.bytes(), align)?;
@ -417,9 +417,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
Some(GlobalAlloc::Memory(mem)) =>
Cow::Borrowed(mem),
Some(GlobalAlloc::Function(..)) =>
return err!(DerefFunctionPointer),
return err!(Unsupported(DerefFunctionPointer)),
None =>
return err!(DanglingPointerDeref),
return err!(Unsupported(DanglingPointerDeref)),
Some(GlobalAlloc::Static(def_id)) => {
// We got a "lazy" static that has not been computed yet.
if tcx.is_foreign_item(def_id) {
@ -440,8 +440,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
// for statics
assert!(tcx.is_static(def_id));
match err {
ErrorHandled::Reported => InterpError::ReferencedConstant,
ErrorHandled::TooGeneric => InterpError::TooGeneric,
ErrorHandled::Reported =>
InterpError::InvalidProgram(ReferencedConstant),
ErrorHandled::TooGeneric =>
InterpError::InvalidProgram(TooGeneric),
}
})?;
// Make sure we use the ID of the resolved memory, not the lazy one!
@ -505,11 +507,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
// to give us a cheap reference.
let alloc = Self::get_static_alloc(memory_extra, tcx, id)?;
if alloc.mutability == Mutability::Immutable {
return err!(ModifiedConstantMemory);
return err!(Unsupported(ModifiedConstantMemory));
}
match M::STATIC_KIND {
Some(kind) => Ok((MemoryKind::Machine(kind), alloc.into_owned())),
None => err!(ModifiedStatic),
None => err!(Unsupported(ModifiedStatic)),
}
});
// Unpack the error type manually because type inference doesn't
@ -519,7 +521,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
Ok(a) => {
let a = &mut a.1;
if a.mutability == Mutability::Immutable {
return err!(ModifiedConstantMemory);
return err!(Unsupported(ModifiedConstantMemory));
}
Ok(a)
}
@ -591,7 +593,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
} else {
match self.tcx.alloc_map.lock().get(id) {
Some(GlobalAlloc::Function(instance)) => Ok(FnVal::Instance(instance)),
_ => Err(InterpError::ExecuteMemory.into()),
_ => Err(InterpError::Unsupported(ExecuteMemory).into()),
}
}
}
@ -602,7 +604,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
) -> InterpResult<'tcx, FnVal<'tcx, M::ExtraFnVal>> {
let ptr = self.force_ptr(ptr)?; // We definitely need a pointer value.
if ptr.offset.bytes() != 0 {
return err!(InvalidFunctionPointer);
return err!(Unsupported(InvalidFunctionPointer));
}
self.get_fn_alloc(ptr.alloc_id)
}
@ -837,9 +839,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
if (src.offset <= dest.offset && src.offset + size > dest.offset) ||
(dest.offset <= src.offset && dest.offset + size > src.offset)
{
return err!(Intrinsic(
return err!(Unsupported(Intrinsic(
"copy_nonoverlapping called on overlapping ranges".to_string(),
));
)));
}
}

View File

@ -12,7 +12,7 @@ use rustc::mir::interpret::{
GlobalId, AllocId,
ConstValue, Pointer, Scalar,
InterpResult, InterpError,
sign_extend, truncate,
sign_extend, truncate, UnsupportedInfo::*, InvalidProgramInfo::*
};
use super::{
InterpCx, Machine,
@ -332,7 +332,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let len = mplace.len(self)?;
let bytes = self.memory.read_bytes(mplace.ptr, Size::from_bytes(len as u64))?;
let str = ::std::str::from_utf8(bytes)
.map_err(|err| InterpError::ValidationFailure(err.to_string()))?;
.map_err(|err| InterpError::Unsupported(ValidationFailure(err.to_string())))?;
Ok(str)
}
@ -459,7 +459,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
mir_place.iterate(|place_base, place_projection| {
let mut op = match place_base {
PlaceBase::Local(mir::RETURN_PLACE) => return err!(ReadFromReturnPointer),
PlaceBase::Local(mir::RETURN_PLACE) =>
return err!(Unsupported(ReadFromReturnPointer)),
PlaceBase::Local(local) => {
// Do not use the layout passed in as argument if the base we are looking at
// here is not the entire place.
@ -530,7 +531,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
};
// Early-return cases.
match val.val {
ConstValue::Param(_) => return err!(TooGeneric), // FIXME(oli-obk): try to monomorphize
ConstValue::Param(_) =>
// FIXME(oli-obk): try to monomorphize
return err!(InvalidProgram(TooGeneric)),
ConstValue::Unevaluated(def_id, substs) => {
let instance = self.resolve(def_id, substs)?;
return Ok(OpTy::from(self.const_eval_raw(GlobalId {
@ -604,7 +607,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
layout::DiscriminantKind::Tag => {
let bits_discr = match raw_discr.to_bits(discr_val.layout.size) {
Ok(raw_discr) => raw_discr,
Err(_) => return err!(InvalidDiscriminant(raw_discr.erase_tag())),
Err(_) =>
return err!(Unsupported(InvalidDiscriminant(raw_discr.erase_tag()))),
};
let real_discr = if discr_val.layout.ty.is_signed() {
// going from layout tag type to typeck discriminant type
@ -630,7 +634,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
.discriminants(*def_id, self.tcx.tcx)
.find(|(_, var)| var.val == real_discr),
_ => bug!("tagged layout for non-adt non-generator"),
}.ok_or_else(|| InterpError::InvalidDiscriminant(raw_discr.erase_tag()))?;
}.ok_or_else(
|| InterpError::Unsupported(InvalidDiscriminant(raw_discr.erase_tag()))
)?;
(real_discr, index.0)
},
layout::DiscriminantKind::Niche {
@ -641,14 +647,14 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let variants_start = niche_variants.start().as_u32() as u128;
let variants_end = niche_variants.end().as_u32() as u128;
let raw_discr = raw_discr.not_undef()
.map_err(|_| InterpError::InvalidDiscriminant(ScalarMaybeUndef::Undef))?;
.map_err(|_| InterpError::Unsupported(InvalidDiscriminant(ScalarMaybeUndef::Undef)))?;
match raw_discr.to_bits_or_ptr(discr_val.layout.size, self) {
Err(ptr) => {
// The niche must be just 0 (which an inbounds pointer value never is)
let ptr_valid = niche_start == 0 && variants_start == variants_end &&
!self.memory.ptr_may_be_null(ptr);
if !ptr_valid {
return err!(InvalidDiscriminant(raw_discr.erase_tag().into()));
return err!(Unsupported(InvalidDiscriminant(raw_discr.erase_tag().into())));
}
(dataful_variant.as_u32() as u128, dataful_variant)
},

View File

@ -4,7 +4,7 @@ use syntax::ast::FloatTy;
use rustc_apfloat::Float;
use rustc::mir::interpret::{InterpResult, PanicMessage, Scalar};
use super::{InterpCx, PlaceTy, Immediate, Machine, ImmTy};
use super::{InterpCx, PlaceTy, Immediate, Machine, ImmTy, UnsupportedInfo::*};
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
@ -155,7 +155,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
r,
right_layout.ty
);
return err!(Unimplemented(msg));
return err!(Unsupported(Unimplemented(msg)));
}
// Operations that need special treatment for signed integers
@ -250,7 +250,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
r,
right_layout.ty,
);
return err!(Unimplemented(msg));
return err!(Unsupported(Unimplemented(msg)));
}
};

View File

@ -14,7 +14,8 @@ use rustc::ty::TypeFoldable;
use super::{
GlobalId, AllocId, Allocation, Scalar, InterpResult, Pointer, PointerArithmetic,
InterpCx, Machine, AllocMap, AllocationExtra, PanicMessage,
RawConst, Immediate, ImmTy, ScalarMaybeUndef, Operand, OpTy, MemoryKind, LocalValue
RawConst, Immediate, ImmTy, ScalarMaybeUndef, Operand, OpTy, MemoryKind, LocalValue,
UnsupportedInfo::*,
};
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
@ -622,7 +623,7 @@ where
.layout_of(self.monomorphize(self.frame().body.return_ty())?)?,
}
}
None => return err!(InvalidNullPointerUsage),
None => return err!(Unsupported(InvalidNullPointerUsage)),
},
PlaceBase::Local(local) => PlaceTy {
// This works even for dead/uninitialized locals; we check further when writing

View File

@ -12,7 +12,7 @@ use rustc::mir;
use rustc::mir::interpret::{
AllocId, Pointer, Scalar,
Relocations, Allocation, UndefMask,
InterpResult, InterpError,
InterpResult, InterpError, ResourceExhaustionInfo::*,
};
use rustc::ty::{self, TyCtxt};
@ -77,7 +77,7 @@ impl<'mir, 'tcx> InfiniteLoopDetector<'mir, 'tcx> {
}
// Second cycle
Err(InterpError::InfiniteLoop.into())
Err(InterpError::ResourceExhaustion(InfiniteLoop).into())
}
}

View File

@ -4,7 +4,7 @@
use rustc::mir;
use rustc::ty::layout::LayoutOf;
use rustc::mir::interpret::{InterpResult, Scalar, PointerArithmetic};
use rustc::mir::interpret::{InterpResult, Scalar, PointerArithmetic, UnsupportedInfo};
use super::{InterpCx, Machine};
@ -121,7 +121,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// size of MIR constantly.
Nop => {}
InlineAsm { .. } => return err!(InlineAsm),
InlineAsm { .. } => return err!(Unsupported(UnsupportedInfo::InlineAsm)),
}
self.stack[frame_idx].stmt += 1;

View File

@ -9,6 +9,7 @@ use rustc_target::spec::abi::Abi;
use super::{
InterpResult, PointerArithmetic, InterpError, Scalar,
InterpCx, Machine, Immediate, OpTy, ImmTy, PlaceTy, MPlaceTy, StackPopCleanup, FnVal,
UndefinedBehaviourInfo, UnsupportedInfo::*,
};
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
@ -19,7 +20,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
self.frame_mut().stmt = 0;
Ok(())
} else {
err!(Unreachable)
err!(UndefinedBehaviour(UndefinedBehaviourInfo::Unreachable))
}
}
@ -89,7 +90,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
},
_ => {
let msg = format!("can't handle callee of type {:?}", func.layout.ty);
return err!(Unimplemented(msg));
return err!(Unsupported(Unimplemented(msg)));
}
};
let args = self.eval_operands(args)?;
@ -173,7 +174,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
`simplify_branches` mir pass"),
FalseUnwind { .. } => bug!("should have been eliminated by\
`simplify_branches` mir pass"),
Unreachable => return err!(Unreachable),
Unreachable => return err!(UndefinedBehaviour(UndefinedBehaviourInfo::Unreachable)),
}
Ok(())
@ -220,13 +221,15 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
return Ok(());
}
let caller_arg = caller_arg.next()
.ok_or_else(|| InterpError::FunctionArgCountMismatch)?;
.ok_or_else(|| InterpError::Unsupported(FunctionArgCountMismatch))?;
if rust_abi {
debug_assert!(!caller_arg.layout.is_zst(), "ZSTs must have been already filtered out");
}
// Now, check
if !Self::check_argument_compat(rust_abi, caller_arg.layout, callee_arg.layout) {
return err!(FunctionArgMismatch(caller_arg.layout.ty, callee_arg.layout.ty));
return err!(
Unsupported(FunctionArgMismatch(caller_arg.layout.ty, callee_arg.layout.ty))
);
}
// We allow some transmutes here
self.copy_op_transmute(caller_arg, callee_arg)
@ -254,13 +257,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
match instance.def {
ty::InstanceDef::Intrinsic(..) => {
if caller_abi != Abi::RustIntrinsic {
return err!(FunctionAbiMismatch(caller_abi, Abi::RustIntrinsic));
return err!(Unsupported(FunctionAbiMismatch(caller_abi, Abi::RustIntrinsic)));
}
// The intrinsic itself cannot diverge, so if we got here without a return
// place... (can happen e.g., for transmute returning `!`)
let dest = match dest {
Some(dest) => dest,
None => return err!(Unreachable)
None => return err!(UndefinedBehaviour(UndefinedBehaviourInfo::Unreachable))
};
M::call_intrinsic(self, instance, args, dest)?;
// No stack frame gets pushed, the main loop will just act as if the
@ -295,7 +298,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
abi,
};
if normalize_abi(caller_abi) != normalize_abi(callee_abi) {
return err!(FunctionAbiMismatch(caller_abi, callee_abi));
return err!(Unsupported(FunctionAbiMismatch(caller_abi, callee_abi)));
}
}
@ -390,7 +393,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// Now we should have no more caller args
if caller_iter.next().is_some() {
trace!("Caller has passed too many args");
return err!(FunctionArgCountMismatch);
return err!(Unsupported(FunctionArgCountMismatch));
}
// Don't forget to check the return type!
if let Some(caller_ret) = dest {
@ -402,15 +405,15 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
caller_ret.layout,
callee_ret.layout,
) {
return err!(FunctionRetMismatch(
caller_ret.layout.ty, callee_ret.layout.ty
return err!(Unsupported(
FunctionRetMismatch(caller_ret.layout.ty, callee_ret.layout.ty)
));
}
} else {
let local = mir::RETURN_PLACE;
let ty = self.frame().body.local_decls[local].ty;
if !self.tcx.is_ty_uninhabited_from_any_module(ty) {
return err!(FunctionRetMismatch(self.tcx.types.never, ty));
return err!(Unsupported(FunctionRetMismatch(self.tcx.types.never, ty)));
}
}
Ok(())

View File

@ -1,6 +1,6 @@
use rustc::ty::{self, Ty, Instance};
use rustc::ty::layout::{Size, Align, LayoutOf};
use rustc::mir::interpret::{Scalar, Pointer, InterpResult, PointerArithmetic};
use rustc::mir::interpret::{Scalar, Pointer, InterpResult, PointerArithmetic, InvalidProgramInfo};
use super::{InterpCx, InterpError, Machine, MemoryKind, FnVal};
@ -83,7 +83,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
self.param_env,
def_id,
substs,
).ok_or_else(|| InterpError::TooGeneric)?;
).ok_or_else(|| InterpError::InvalidProgram(InvalidProgramInfo::TooGeneric))?;
let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance));
let method_ptr = vtable.offset(ptr_size * (3 + i as u64), self)?;
self.memory

View File

@ -11,7 +11,7 @@ use std::hash::Hash;
use super::{
GlobalAlloc, InterpResult, InterpError,
OpTy, Machine, InterpCx, ValueVisitor, MPlaceTy,
OpTy, Machine, InterpCx, ValueVisitor, MPlaceTy, UnsupportedInfo::*,
};
macro_rules! validation_failure {
@ -22,10 +22,10 @@ macro_rules! validation_failure {
} else {
format!(" at {}", where_)
};
err!(ValidationFailure(format!(
err!(Unsupported(ValidationFailure(format!(
"encountered {}{}, but expected {}",
$what, where_, $details,
)))
))))
}};
($what:expr, $where:expr) => {{
let where_ = path_format(&$where);
@ -34,10 +34,10 @@ macro_rules! validation_failure {
} else {
format!(" at {}", where_)
};
err!(ValidationFailure(format!(
err!(Unsupported(ValidationFailure(format!(
"encountered {}{}",
$what, where_,
)))
))))
}};
}
@ -297,11 +297,11 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
match self.walk_value(op) {
Ok(()) => Ok(()),
Err(err) => match err.kind {
InterpError::InvalidDiscriminant(val) =>
InterpError::Unsupported(InvalidDiscriminant(val)) =>
validation_failure!(
val, self.path, "a valid enum discriminant"
),
InterpError::ReadPointerAsBytes =>
InterpError::Unsupported(ReadPointerAsBytes) =>
validation_failure!(
"a pointer", self.path, "plain (non-pointer) bytes"
),
@ -406,13 +406,13 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
ptr, size, align
);
match err.kind {
InterpError::InvalidNullPointerUsage =>
InterpError::Unsupported(InvalidNullPointerUsage) =>
return validation_failure!("NULL reference", self.path),
InterpError::AlignmentCheckFailed { required, has } =>
InterpError::Unsupported(AlignmentCheckFailed { required, has }) =>
return validation_failure!(format!("unaligned reference \
(required {} byte alignment but found {})",
required.bytes(), has.bytes()), self.path),
InterpError::ReadBytesAsPointer =>
InterpError::Unsupported(ReadBytesAsPointer) =>
return validation_failure!(
"dangling reference (created from integer)",
self.path
@ -608,7 +608,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
Err(err) => {
// For some errors we might be able to provide extra information
match err.kind {
InterpError::ReadUndefBytes(offset) => {
InterpError::Unsupported(ReadUndefBytes(offset)) => {
// Some byte was undefined, determine which
// element that byte belongs to so we can
// provide an index.

View File

@ -257,86 +257,20 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
Err(error) => {
let diagnostic = error_to_const_error(&self.ecx, error);
use rustc::mir::interpret::InterpError::*;
use rustc::mir::interpret::UnsupportedInfo::*;
match diagnostic.error {
// don't report these, they make no sense in a const prop context
| MachineError(_)
| Exit(_)
// at runtime these transformations might make sense
// FIXME: figure out the rules and start linting
| FunctionAbiMismatch(..)
| FunctionArgMismatch(..)
| FunctionRetMismatch(..)
| FunctionArgCountMismatch
// fine at runtime, might be a register address or sth
| ReadBytesAsPointer
// fine at runtime
| ReadForeignStatic
| Unimplemented(_)
// don't report const evaluator limits
| StackFrameLimitReached
| NoMirFor(..)
| InlineAsm
=> {},
Exit(_) => {},
| InvalidMemoryAccess
| DanglingPointerDeref
| DoubleFree
| InvalidFunctionPointer
| InvalidBool
| InvalidDiscriminant(..)
| PointerOutOfBounds { .. }
| InvalidNullPointerUsage
| ValidationFailure(..)
| InvalidPointerMath
| ReadUndefBytes(_)
| DeadLocal
| InvalidBoolOp(_)
| DerefFunctionPointer
| ExecuteMemory
| Intrinsic(..)
| InvalidChar(..)
| AbiViolation(_)
| AlignmentCheckFailed{..}
| CalledClosureAsFunction
| VtableForArgumentlessMethod
| ModifiedConstantMemory
| ModifiedStatic
| AssumptionNotHeld
// FIXME: should probably be removed and turned into a bug! call
| TypeNotPrimitive(_)
| ReallocatedWrongMemoryKind(_, _)
| DeallocatedWrongMemoryKind(_, _)
| ReallocateNonBasePtr
| DeallocateNonBasePtr
| IncorrectAllocationInformation(..)
| UnterminatedCString(_)
| HeapAllocZeroBytes
| HeapAllocNonPowerOfTwoAlignment(_)
| Unreachable
| ReadFromReturnPointer
| ReferencedConstant
| InfiniteLoop
=> {
// FIXME: report UB here
},
| OutOfTls
| TlsOutOfBounds
| PathNotFound(_)
| Unsupported(OutOfTls)
| Unsupported(TlsOutOfBounds)
| Unsupported(PathNotFound(_))
=> bug!("these should not be in rustc, but in miri's machine errors"),
| Layout(_)
| UnimplementedTraitSelection
| TypeckError
| TooGeneric
// these are just noise
=> {},
// non deterministic
| ReadPointerAsBytes
// FIXME: implement
=> {},
| Unsupported(_) => {},
| UndefinedBehaviour(_) => {},
| InvalidProgram(_) => {},
| ResourceExhaustion(_) => {},
| Panic(_)
=> {
diagnostic.report_as_lint(