Rollup merge of #62927 - RalfJung:panic, r=oli-obk
use PanicMessage in MIR, kill InterpError::description r? @oli-obk @eddyb Cc @saleemjaffer https://github.com/rust-rfcs/const-eval/issues/4
This commit is contained in:
commit
e27927d2ff
12 changed files with 241 additions and 238 deletions
|
@ -47,7 +47,7 @@ pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ErrorHandled>;
|
|||
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub struct ConstEvalErr<'tcx> {
|
||||
pub span: Span,
|
||||
pub error: crate::mir::interpret::InterpError<'tcx, u64>,
|
||||
pub error: crate::mir::interpret::InterpError<'tcx>,
|
||||
pub stacktrace: Vec<FrameInfo<'tcx>>,
|
||||
}
|
||||
|
||||
|
@ -185,11 +185,18 @@ pub fn struct_error<'tcx>(tcx: TyCtxtAt<'tcx>, msg: &str) -> DiagnosticBuilder<'
|
|||
/// macro for this.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct InterpErrorInfo<'tcx> {
|
||||
pub kind: InterpError<'tcx, u64>,
|
||||
pub kind: InterpError<'tcx>,
|
||||
backtrace: Option<Box<Backtrace>>,
|
||||
}
|
||||
|
||||
impl<'tcx> InterpErrorInfo<'tcx> {
|
||||
|
||||
impl fmt::Display for InterpErrorInfo<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.kind)
|
||||
}
|
||||
}
|
||||
|
||||
impl InterpErrorInfo<'_> {
|
||||
pub fn print_backtrace(&mut self) {
|
||||
if let Some(ref mut backtrace) = self.backtrace {
|
||||
print_backtrace(&mut *backtrace);
|
||||
|
@ -202,8 +209,8 @@ fn print_backtrace(backtrace: &mut Backtrace) {
|
|||
eprintln!("\n\nAn error occurred in miri:\n{:?}", backtrace);
|
||||
}
|
||||
|
||||
impl<'tcx> From<InterpError<'tcx, u64>> for InterpErrorInfo<'tcx> {
|
||||
fn from(kind: InterpError<'tcx, u64>) -> Self {
|
||||
impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
|
||||
fn from(kind: InterpError<'tcx>) -> Self {
|
||||
let backtrace = match env::var("RUST_CTFE_BACKTRACE") {
|
||||
// Matching `RUST_BACKTRACE` -- we treat "0" the same as "not present".
|
||||
Ok(ref val) if val != "0" => {
|
||||
|
@ -226,8 +233,6 @@ impl<'tcx> From<InterpError<'tcx, u64>> for InterpErrorInfo<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub type AssertMessage<'tcx> = InterpError<'tcx, mir::Operand<'tcx>>;
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
|
||||
pub enum PanicMessage<O> {
|
||||
Panic {
|
||||
|
@ -244,10 +249,68 @@ pub enum PanicMessage<O> {
|
|||
OverflowNeg,
|
||||
DivisionByZero,
|
||||
RemainderByZero,
|
||||
GeneratorResumedAfterReturn,
|
||||
GeneratorResumedAfterPanic,
|
||||
}
|
||||
|
||||
/// Type for MIR `Assert` terminator error messages.
|
||||
pub type AssertMessage<'tcx> = PanicMessage<mir::Operand<'tcx>>;
|
||||
|
||||
impl<O> PanicMessage<O> {
|
||||
/// Getting a description does not require `O` to be printable, and does not
|
||||
/// require allocation.
|
||||
/// The caller is expected to handle `Panic` and `BoundsCheck` separately.
|
||||
pub fn description(&self) -> &'static str {
|
||||
use PanicMessage::*;
|
||||
match self {
|
||||
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",
|
||||
Panic { .. } | BoundsCheck { .. } =>
|
||||
bug!("Unexpected PanicMessage"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<O: fmt::Debug> fmt::Debug for PanicMessage<O> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use PanicMessage::*;
|
||||
match self {
|
||||
Panic { ref msg, line, col, ref file } =>
|
||||
write!(f, "the evaluated program panicked at '{}', {}:{}:{}", msg, file, line, col),
|
||||
BoundsCheck { ref len, ref index } =>
|
||||
write!(f, "index out of bounds: the len is {:?} but the index is {:?}", len, index),
|
||||
_ =>
|
||||
write!(f, "{}", self.description()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
|
||||
pub enum InterpError<'tcx, O> {
|
||||
pub enum InterpError<'tcx> {
|
||||
/// This variant is used by machines to signal their own errors that do not
|
||||
/// match an existing variant.
|
||||
MachineError(String),
|
||||
|
@ -311,7 +374,7 @@ pub enum InterpError<'tcx, O> {
|
|||
HeapAllocZeroBytes,
|
||||
HeapAllocNonPowerOfTwoAlignment(u64),
|
||||
Unreachable,
|
||||
Panic(PanicMessage<O>),
|
||||
Panic(PanicMessage<u64>),
|
||||
ReadFromReturnPointer,
|
||||
PathNotFound(Vec<String>),
|
||||
UnimplementedTraitSelection,
|
||||
|
@ -322,173 +385,21 @@ pub enum InterpError<'tcx, O> {
|
|||
/// Cannot compute this constant because it depends on another one
|
||||
/// which already produced an error
|
||||
ReferencedConstant,
|
||||
GeneratorResumedAfterReturn,
|
||||
GeneratorResumedAfterPanic,
|
||||
InfiniteLoop,
|
||||
}
|
||||
|
||||
pub type InterpResult<'tcx, T = ()> = Result<T, InterpErrorInfo<'tcx>>;
|
||||
|
||||
impl<'tcx, O> InterpError<'tcx, O> {
|
||||
pub fn description(&self) -> &str {
|
||||
use self::InterpError::*;
|
||||
match *self {
|
||||
MachineError(ref inner) => inner,
|
||||
Exit(..) =>
|
||||
"exited",
|
||||
FunctionAbiMismatch(..) | FunctionArgMismatch(..) | FunctionRetMismatch(..)
|
||||
| FunctionArgCountMismatch =>
|
||||
"tried to call a function through a function pointer of incompatible type",
|
||||
InvalidMemoryAccess =>
|
||||
"tried to access memory through an invalid pointer",
|
||||
DanglingPointerDeref =>
|
||||
"dangling pointer was dereferenced",
|
||||
DoubleFree =>
|
||||
"tried to deallocate dangling pointer",
|
||||
InvalidFunctionPointer =>
|
||||
"tried to use a function pointer after offsetting it",
|
||||
InvalidBool =>
|
||||
"invalid boolean value read",
|
||||
InvalidDiscriminant(..) =>
|
||||
"invalid enum discriminant value read",
|
||||
PointerOutOfBounds { .. } =>
|
||||
"pointer offset outside bounds of allocation",
|
||||
InvalidNullPointerUsage =>
|
||||
"invalid use of NULL pointer",
|
||||
ValidationFailure(..) =>
|
||||
"type validation failed",
|
||||
ReadPointerAsBytes =>
|
||||
"a raw memory access tried to access part of a pointer value as raw bytes",
|
||||
ReadBytesAsPointer =>
|
||||
"a memory access tried to interpret some bytes as a pointer",
|
||||
ReadForeignStatic =>
|
||||
"tried to read from foreign (extern) static",
|
||||
InvalidPointerMath =>
|
||||
"attempted to do invalid arithmetic on pointers that would leak base addresses, \
|
||||
e.g., comparing pointers into different allocations",
|
||||
ReadUndefBytes(_) =>
|
||||
"attempted to read undefined bytes",
|
||||
DeadLocal =>
|
||||
"tried to access a dead local variable",
|
||||
InvalidBoolOp(_) =>
|
||||
"invalid boolean operation",
|
||||
Unimplemented(ref msg) => msg,
|
||||
DerefFunctionPointer =>
|
||||
"tried to dereference a function pointer",
|
||||
ExecuteMemory =>
|
||||
"tried to treat a memory pointer as a function pointer",
|
||||
Intrinsic(..) =>
|
||||
"intrinsic failed",
|
||||
NoMirFor(..) =>
|
||||
"mir not found",
|
||||
InvalidChar(..) =>
|
||||
"tried to interpret an invalid 32-bit value as a char",
|
||||
StackFrameLimitReached =>
|
||||
"reached the configured maximum number of stack frames",
|
||||
OutOfTls =>
|
||||
"reached the maximum number of representable TLS keys",
|
||||
TlsOutOfBounds =>
|
||||
"accessed an invalid (unallocated) TLS key",
|
||||
AbiViolation(ref msg) => msg,
|
||||
AlignmentCheckFailed{..} =>
|
||||
"tried to execute a misaligned read or write",
|
||||
CalledClosureAsFunction =>
|
||||
"tried to call a closure through a function pointer",
|
||||
VtableForArgumentlessMethod =>
|
||||
"tried to call a vtable function without arguments",
|
||||
ModifiedConstantMemory =>
|
||||
"tried to modify constant memory",
|
||||
ModifiedStatic =>
|
||||
"tried to modify a static's initial value from another static's initializer",
|
||||
AssumptionNotHeld =>
|
||||
"`assume` argument was false",
|
||||
InlineAsm =>
|
||||
"miri does not support inline assembly",
|
||||
TypeNotPrimitive(_) =>
|
||||
"expected primitive type, got nonprimitive",
|
||||
ReallocatedWrongMemoryKind(_, _) =>
|
||||
"tried to reallocate memory from one kind to another",
|
||||
DeallocatedWrongMemoryKind(_, _) =>
|
||||
"tried to deallocate memory of the wrong kind",
|
||||
ReallocateNonBasePtr =>
|
||||
"tried to reallocate with a pointer not to the beginning of an existing object",
|
||||
DeallocateNonBasePtr =>
|
||||
"tried to deallocate with a pointer not to the beginning of an existing object",
|
||||
IncorrectAllocationInformation(..) =>
|
||||
"tried to deallocate or reallocate using incorrect alignment or size",
|
||||
Layout(_) =>
|
||||
"rustc layout computation failed",
|
||||
UnterminatedCString(_) =>
|
||||
"attempted to get length of a null terminated string, but no null found before end \
|
||||
of allocation",
|
||||
HeapAllocZeroBytes =>
|
||||
"tried to re-, de- or allocate zero bytes on the heap",
|
||||
HeapAllocNonPowerOfTwoAlignment(_) =>
|
||||
"tried to re-, de-, or allocate heap memory with alignment that is not a power of \
|
||||
two",
|
||||
Unreachable =>
|
||||
"entered unreachable code",
|
||||
Panic(PanicMessage::Panic{..}) =>
|
||||
"the evaluated program panicked",
|
||||
Panic(PanicMessage::BoundsCheck{..}) =>
|
||||
"array index out of bounds",
|
||||
Panic(PanicMessage::Overflow(mir::BinOp::Add)) =>
|
||||
"attempt to add with overflow",
|
||||
Panic(PanicMessage::Overflow(mir::BinOp::Sub)) =>
|
||||
"attempt to subtract with overflow",
|
||||
Panic(PanicMessage::Overflow(mir::BinOp::Mul)) =>
|
||||
"attempt to multiply with overflow",
|
||||
Panic(PanicMessage::Overflow(mir::BinOp::Div)) =>
|
||||
"attempt to divide with overflow",
|
||||
Panic(PanicMessage::Overflow(mir::BinOp::Rem)) =>
|
||||
"attempt to calculate the remainder with overflow",
|
||||
Panic(PanicMessage::OverflowNeg) =>
|
||||
"attempt to negate with overflow",
|
||||
Panic(PanicMessage::Overflow(mir::BinOp::Shr)) =>
|
||||
"attempt to shift right with overflow",
|
||||
Panic(PanicMessage::Overflow(mir::BinOp::Shl)) =>
|
||||
"attempt to shift left with overflow",
|
||||
Panic(PanicMessage::Overflow(op)) =>
|
||||
bug!("{:?} cannot overflow", op),
|
||||
Panic(PanicMessage::DivisionByZero) =>
|
||||
"attempt to divide by zero",
|
||||
Panic(PanicMessage::RemainderByZero) =>
|
||||
"attempt to calculate the remainder with a divisor of zero",
|
||||
ReadFromReturnPointer =>
|
||||
"tried to read from the return pointer",
|
||||
PathNotFound(_) =>
|
||||
"a path could not be resolved, maybe the crate is not loaded",
|
||||
UnimplementedTraitSelection =>
|
||||
"there were unresolved type arguments during trait selection",
|
||||
TypeckError =>
|
||||
"encountered constants with type errors, stopping evaluation",
|
||||
TooGeneric =>
|
||||
"encountered overly generic constant",
|
||||
ReferencedConstant =>
|
||||
"referenced constant has errors",
|
||||
GeneratorResumedAfterReturn => "generator resumed after completion",
|
||||
GeneratorResumedAfterPanic => "generator resumed after panicking",
|
||||
InfiniteLoop =>
|
||||
"duplicate interpreter state observed here, const evaluation will never terminate",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Display for InterpErrorInfo<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.kind)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Display for InterpError<'tcx, u64> {
|
||||
impl fmt::Display for InterpError<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
// Forward `Display` to `Debug`
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, O: fmt::Debug> fmt::Debug for InterpError<'tcx, O> {
|
||||
impl fmt::Debug for InterpError<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use self::InterpError::*;
|
||||
use InterpError::*;
|
||||
match *self {
|
||||
PointerOutOfBounds { ptr, msg, allocation_size } => {
|
||||
write!(f, "{} failed: pointer must be in-bounds at offset {}, \
|
||||
|
@ -516,8 +427,6 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for InterpError<'tcx, O> {
|
|||
write!(f, "tried to reallocate memory from {} to {}", old, new),
|
||||
DeallocatedWrongMemoryKind(ref old, ref new) =>
|
||||
write!(f, "tried to deallocate {} memory but gave {} as the kind", old, new),
|
||||
Intrinsic(ref err) =>
|
||||
write!(f, "{}", err),
|
||||
InvalidChar(c) =>
|
||||
write!(f, "tried to interpret an invalid 32-bit value as a char: {}", c),
|
||||
AlignmentCheckFailed { required, has } =>
|
||||
|
@ -529,21 +438,101 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for InterpError<'tcx, O> {
|
|||
write!(f, "rustc layout computation failed: {:?}", err),
|
||||
PathNotFound(ref path) =>
|
||||
write!(f, "Cannot find path {:?}", path),
|
||||
MachineError(ref inner) =>
|
||||
write!(f, "{}", inner),
|
||||
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()),
|
||||
Panic(PanicMessage::Panic { ref msg, line, col, ref file }) =>
|
||||
write!(f, "the evaluated program panicked at '{}', {}:{}:{}", msg, file, line, col),
|
||||
Panic(PanicMessage::BoundsCheck { ref len, ref index }) =>
|
||||
write!(f, "index out of bounds: the len is {:?} but the index is {:?}", len, index),
|
||||
InvalidDiscriminant(val) =>
|
||||
write!(f, "encountered invalid enum discriminant {}", val),
|
||||
Exit(code) =>
|
||||
write!(f, "exited with status code {}", code),
|
||||
_ => write!(f, "{}", self.description()),
|
||||
InvalidMemoryAccess =>
|
||||
write!(f, "tried to access memory through an invalid pointer"),
|
||||
DanglingPointerDeref =>
|
||||
write!(f, "dangling pointer was dereferenced"),
|
||||
DoubleFree =>
|
||||
write!(f, "tried to deallocate dangling pointer"),
|
||||
InvalidFunctionPointer =>
|
||||
write!(f, "tried to use a function pointer after offsetting it"),
|
||||
InvalidBool =>
|
||||
write!(f, "invalid boolean value read"),
|
||||
InvalidNullPointerUsage =>
|
||||
write!(f, "invalid use of NULL pointer"),
|
||||
ReadPointerAsBytes =>
|
||||
write!(f, "a raw memory access tried to access part of a pointer value as raw \
|
||||
bytes"),
|
||||
ReadBytesAsPointer =>
|
||||
write!(f, "a memory access tried to interpret some bytes as a pointer"),
|
||||
ReadForeignStatic =>
|
||||
write!(f, "tried to read from foreign (extern) static"),
|
||||
InvalidPointerMath =>
|
||||
write!(f, "attempted to do invalid arithmetic on pointers that would leak base \
|
||||
addresses, e.g., comparing pointers into different allocations"),
|
||||
DeadLocal =>
|
||||
write!(f, "tried to access a dead local variable"),
|
||||
DerefFunctionPointer =>
|
||||
write!(f, "tried to dereference a function pointer"),
|
||||
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 =>
|
||||
write!(f, "reached the maximum number of representable TLS keys"),
|
||||
TlsOutOfBounds =>
|
||||
write!(f, "accessed an invalid (unallocated) TLS key"),
|
||||
CalledClosureAsFunction =>
|
||||
write!(f, "tried to call a closure through a function pointer"),
|
||||
VtableForArgumentlessMethod =>
|
||||
write!(f, "tried to call a vtable function without arguments"),
|
||||
ModifiedConstantMemory =>
|
||||
write!(f, "tried to modify constant memory"),
|
||||
ModifiedStatic =>
|
||||
write!(f, "tried to modify a static's initial value from another static's \
|
||||
initializer"),
|
||||
AssumptionNotHeld =>
|
||||
write!(f, "`assume` argument was false"),
|
||||
InlineAsm =>
|
||||
write!(f, "miri does not support inline assembly"),
|
||||
ReallocateNonBasePtr =>
|
||||
write!(f, "tried to reallocate with a pointer not to the beginning of an \
|
||||
existing object"),
|
||||
DeallocateNonBasePtr =>
|
||||
write!(f, "tried to deallocate with a pointer not to the beginning of an \
|
||||
existing object"),
|
||||
HeapAllocZeroBytes =>
|
||||
write!(f, "tried to re-, de- or allocate zero bytes on the heap"),
|
||||
Unreachable =>
|
||||
write!(f, "entered unreachable code"),
|
||||
ReadFromReturnPointer =>
|
||||
write!(f, "tried to read from the return pointer"),
|
||||
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(_) =>
|
||||
write!(f, "invalid boolean operation"),
|
||||
UnterminatedCString(_) =>
|
||||
write!(f, "attempted to get length of a null terminated string, but no null \
|
||||
found before end of allocation"),
|
||||
ReadUndefBytes(_) =>
|
||||
write!(f, "attempted to read undefined bytes"),
|
||||
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) =>
|
||||
write!(f, "{}", msg),
|
||||
Panic(ref msg) =>
|
||||
write!(f, "{:?}", msg),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
use crate::hir::def::{CtorKind, Namespace};
|
||||
use crate::hir::def_id::DefId;
|
||||
use crate::hir::{self, InlineAsm as HirInlineAsm};
|
||||
use crate::mir::interpret::{ConstValue, PanicMessage, InterpError::Panic, Scalar};
|
||||
use crate::mir::interpret::{ConstValue, PanicMessage, Scalar};
|
||||
use crate::mir::visit::MirVisitable;
|
||||
use crate::rustc_serialize as serialize;
|
||||
use crate::ty::adjustment::PointerCast;
|
||||
|
@ -3152,13 +3152,16 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
|
|||
}
|
||||
}
|
||||
Assert { ref cond, expected, ref msg, target, cleanup } => {
|
||||
let msg = if let Panic(PanicMessage::BoundsCheck { ref len, ref index }) = *msg {
|
||||
Panic(PanicMessage::BoundsCheck {
|
||||
len: len.fold_with(folder),
|
||||
index: index.fold_with(folder),
|
||||
})
|
||||
} else {
|
||||
msg.clone()
|
||||
use PanicMessage::*;
|
||||
let msg = match msg {
|
||||
BoundsCheck { ref len, ref index } =>
|
||||
BoundsCheck {
|
||||
len: len.fold_with(folder),
|
||||
index: index.fold_with(folder),
|
||||
},
|
||||
Panic { .. } | Overflow(_) | OverflowNeg | DivisionByZero | RemainderByZero |
|
||||
GeneratorResumedAfterReturn | GeneratorResumedAfterPanic =>
|
||||
msg.clone(),
|
||||
};
|
||||
Assert { cond: cond.fold_with(folder), expected, msg, target, cleanup }
|
||||
}
|
||||
|
@ -3197,10 +3200,14 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
|
|||
}
|
||||
Assert { ref cond, ref msg, .. } => {
|
||||
if cond.visit_with(visitor) {
|
||||
if let Panic(PanicMessage::BoundsCheck { ref len, ref index }) = *msg {
|
||||
len.visit_with(visitor) || index.visit_with(visitor)
|
||||
} else {
|
||||
false
|
||||
use PanicMessage::*;
|
||||
match msg {
|
||||
BoundsCheck { ref len, ref index } =>
|
||||
len.visit_with(visitor) || index.visit_with(visitor),
|
||||
Panic { .. } | Overflow(_) | OverflowNeg |
|
||||
DivisionByZero | RemainderByZero |
|
||||
GeneratorResumedAfterReturn | GeneratorResumedAfterPanic =>
|
||||
false
|
||||
}
|
||||
} else {
|
||||
false
|
||||
|
|
|
@ -514,11 +514,16 @@ macro_rules! make_mir_visitor {
|
|||
fn super_assert_message(&mut self,
|
||||
msg: & $($mutability)? AssertMessage<'tcx>,
|
||||
location: Location) {
|
||||
use crate::mir::interpret::InterpError::*;
|
||||
use crate::mir::interpret::PanicMessage::BoundsCheck;
|
||||
if let Panic(BoundsCheck { len, index }) = msg {
|
||||
self.visit_operand(len, location);
|
||||
self.visit_operand(index, location);
|
||||
use crate::mir::interpret::PanicMessage::*;
|
||||
match msg {
|
||||
BoundsCheck { len, index } => {
|
||||
self.visit_operand(len, location);
|
||||
self.visit_operand(index, location);
|
||||
}
|
||||
Panic { .. } | Overflow(_) | OverflowNeg | DivisionByZero | RemainderByZero |
|
||||
GeneratorResumedAfterReturn | GeneratorResumedAfterPanic => {
|
||||
// Nothing to visit
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ use rustc::middle::lang_items;
|
|||
use rustc::ty::{self, Ty, TypeFoldable, Instance};
|
||||
use rustc::ty::layout::{self, LayoutOf, HasTyCtxt, FnTypeExt};
|
||||
use rustc::mir::{self, Place, PlaceBase, Static, StaticKind};
|
||||
use rustc::mir::interpret::{InterpError, PanicMessage};
|
||||
use rustc::mir::interpret::PanicMessage;
|
||||
use rustc_target::abi::call::{ArgType, FnType, PassMode, IgnoreMode};
|
||||
use rustc_target::spec::abi::Abi;
|
||||
use crate::base;
|
||||
|
@ -368,7 +368,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
// checked operation, just a comparison with the minimum
|
||||
// value, so we have to check for the assert message.
|
||||
if !bx.check_overflow() {
|
||||
if let InterpError::Panic(PanicMessage::OverflowNeg) = *msg {
|
||||
if let PanicMessage::OverflowNeg = *msg {
|
||||
const_cond = Some(expected);
|
||||
}
|
||||
}
|
||||
|
@ -402,8 +402,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
let col = bx.const_u32(loc.col.to_usize() as u32 + 1);
|
||||
|
||||
// Put together the arguments to the panic entry point.
|
||||
let (lang_item, args) = match *msg {
|
||||
InterpError::Panic(PanicMessage::BoundsCheck { ref len, ref index }) => {
|
||||
let (lang_item, args) = match msg {
|
||||
PanicMessage::BoundsCheck { ref len, ref index } => {
|
||||
let len = self.codegen_operand(&mut bx, len).immediate();
|
||||
let index = self.codegen_operand(&mut bx, index).immediate();
|
||||
|
||||
|
|
|
@ -733,8 +733,8 @@ impl<'cx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx
|
|||
cleanup: _,
|
||||
} => {
|
||||
self.consume_operand(loc, (cond, span), flow_state);
|
||||
use rustc::mir::interpret::{InterpError::Panic, PanicMessage};
|
||||
if let Panic(PanicMessage::BoundsCheck { ref len, ref index }) = *msg {
|
||||
use rustc::mir::interpret::PanicMessage;
|
||||
if let PanicMessage::BoundsCheck { ref len, ref index } = *msg {
|
||||
self.consume_operand(loc, (len, span), flow_state);
|
||||
self.consume_operand(loc, (index, span), flow_state);
|
||||
}
|
||||
|
|
|
@ -207,8 +207,8 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
|
|||
cleanup: _,
|
||||
} => {
|
||||
self.consume_operand(location, cond);
|
||||
use rustc::mir::interpret::{InterpError::Panic, PanicMessage::BoundsCheck};
|
||||
if let Panic(BoundsCheck { ref len, ref index }) = *msg {
|
||||
use rustc::mir::interpret::PanicMessage;
|
||||
if let PanicMessage::BoundsCheck { ref len, ref index } = *msg {
|
||||
self.consume_operand(location, len);
|
||||
self.consume_operand(location, index);
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ use rustc::infer::canonical::QueryRegionConstraints;
|
|||
use rustc::infer::outlives::env::RegionBoundPairs;
|
||||
use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin};
|
||||
use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
|
||||
use rustc::mir::interpret::{InterpError::Panic, ConstValue, PanicMessage};
|
||||
use rustc::mir::interpret::{ConstValue, PanicMessage};
|
||||
use rustc::mir::tcx::PlaceTy;
|
||||
use rustc::mir::visit::{PlaceContext, Visitor, NonMutatingUseContext};
|
||||
use rustc::mir::*;
|
||||
|
@ -1606,7 +1606,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
|||
span_mirbug!(self, term, "bad Assert ({:?}, not bool", cond_ty);
|
||||
}
|
||||
|
||||
if let Panic(PanicMessage::BoundsCheck { ref len, ref index }) = *msg {
|
||||
if let PanicMessage::BoundsCheck { ref len, ref index } = *msg {
|
||||
if len.ty(body, tcx) != tcx.types.usize {
|
||||
span_mirbug!(self, len, "bounds-check length non-usize {:?}", len)
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use crate::build::expr::category::Category;
|
|||
use crate::build::ForGuard::{OutsideGuard, RefWithinGuard};
|
||||
use crate::build::{BlockAnd, BlockAndExtension, Builder};
|
||||
use crate::hair::*;
|
||||
use rustc::mir::interpret::{InterpError::Panic, PanicMessage::BoundsCheck};
|
||||
use rustc::mir::interpret::{PanicMessage::BoundsCheck};
|
||||
use rustc::mir::*;
|
||||
use rustc::ty::{CanonicalUserTypeAnnotation, Variance};
|
||||
|
||||
|
@ -105,10 +105,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
),
|
||||
);
|
||||
|
||||
let msg = Panic(BoundsCheck {
|
||||
let msg = BoundsCheck {
|
||||
len: Operand::Move(len),
|
||||
index: Operand::Copy(Place::from(idx)),
|
||||
});
|
||||
};
|
||||
let success = this.assert(block, Operand::Move(lt), true, msg, expr_span);
|
||||
success.and(slice.index(idx))
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::build::expr::category::{Category, RvalueFunc};
|
|||
use crate::build::{BlockAnd, BlockAndExtension, Builder};
|
||||
use crate::hair::*;
|
||||
use rustc::middle::region;
|
||||
use rustc::mir::interpret::{InterpError::Panic, PanicMessage};
|
||||
use rustc::mir::interpret::PanicMessage;
|
||||
use rustc::mir::*;
|
||||
use rustc::ty::{self, CanonicalUserTypeAnnotation, Ty, UpvarSubsts};
|
||||
use syntax_pos::Span;
|
||||
|
@ -101,7 +101,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
block,
|
||||
Operand::Move(is_min),
|
||||
false,
|
||||
Panic(PanicMessage::OverflowNeg),
|
||||
PanicMessage::OverflowNeg,
|
||||
expr_span,
|
||||
);
|
||||
}
|
||||
|
@ -401,7 +401,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
let val = result_value.clone().field(val_fld, ty);
|
||||
let of = result_value.field(of_fld, bool_ty);
|
||||
|
||||
let err = Panic(PanicMessage::Overflow(op));
|
||||
let err = PanicMessage::Overflow(op);
|
||||
|
||||
block = self.assert(block, Operand::Move(of), false, err, span);
|
||||
|
||||
|
@ -411,11 +411,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
// Checking division and remainder is more complex, since we 1. always check
|
||||
// and 2. there are two possible failure cases, divide-by-zero and overflow.
|
||||
|
||||
let (zero_err, overflow_err) = if op == BinOp::Div {
|
||||
(Panic(PanicMessage::DivisionByZero), Panic(PanicMessage::Overflow(op)))
|
||||
let zero_err = if op == BinOp::Div {
|
||||
PanicMessage::DivisionByZero
|
||||
} else {
|
||||
(Panic(PanicMessage::RemainderByZero), Panic(PanicMessage::Overflow(op)))
|
||||
PanicMessage::RemainderByZero
|
||||
};
|
||||
let overflow_err = PanicMessage::Overflow(op);
|
||||
|
||||
// Check for / 0
|
||||
let is_zero = self.temp(bool_ty, span);
|
||||
|
|
|
@ -7,7 +7,7 @@ use syntax::source_map::Span;
|
|||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
use super::{
|
||||
InterpResult, PointerArithmetic, InterpError, Scalar, PanicMessage,
|
||||
InterpResult, PointerArithmetic, InterpError, Scalar,
|
||||
InterpCx, Machine, Immediate, OpTy, ImmTy, PlaceTy, MPlaceTy, StackPopCleanup, FnVal,
|
||||
};
|
||||
|
||||
|
@ -135,28 +135,31 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||
self.goto_block(Some(target))?;
|
||||
} else {
|
||||
// Compute error message
|
||||
use rustc::mir::interpret::InterpError::*;
|
||||
return match *msg {
|
||||
Panic(PanicMessage::BoundsCheck { ref len, ref index }) => {
|
||||
use rustc::mir::interpret::PanicMessage::*;
|
||||
return match msg {
|
||||
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!(Panic(PanicMessage::BoundsCheck { len, index }))
|
||||
err!(Panic(BoundsCheck { len, index }))
|
||||
}
|
||||
Panic(PanicMessage::Overflow(op)) =>
|
||||
Err(Panic(PanicMessage::Overflow(op)).into()),
|
||||
Panic(PanicMessage::OverflowNeg) =>
|
||||
Err(Panic(PanicMessage::OverflowNeg).into()),
|
||||
Panic(PanicMessage::DivisionByZero) =>
|
||||
Err(Panic(PanicMessage::DivisionByZero).into()),
|
||||
Panic(PanicMessage::RemainderByZero) =>
|
||||
Err(Panic(PanicMessage::RemainderByZero).into()),
|
||||
GeneratorResumedAfterReturn |
|
||||
GeneratorResumedAfterPanic => unimplemented!(),
|
||||
_ => bug!(),
|
||||
Overflow(op) =>
|
||||
err!(Panic(Overflow(*op))),
|
||||
OverflowNeg =>
|
||||
err!(Panic(OverflowNeg)),
|
||||
DivisionByZero =>
|
||||
err!(Panic(DivisionByZero)),
|
||||
RemainderByZero =>
|
||||
err!(Panic(RemainderByZero)),
|
||||
GeneratorResumedAfterReturn =>
|
||||
err!(Panic(GeneratorResumedAfterReturn)),
|
||||
GeneratorResumedAfterPanic =>
|
||||
err!(Panic(GeneratorResumedAfterPanic)),
|
||||
Panic { .. } =>
|
||||
bug!("`Panic` variant cannot occur in MIR"),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ use rustc::mir::{
|
|||
use rustc::mir::visit::{
|
||||
Visitor, PlaceContext, MutatingUseContext, MutVisitor, NonMutatingUseContext,
|
||||
};
|
||||
use rustc::mir::interpret::{InterpError::Panic, Scalar, GlobalId, InterpResult, PanicMessage};
|
||||
use rustc::mir::interpret::{Scalar, GlobalId, InterpResult, InterpError, PanicMessage};
|
||||
use rustc::ty::{self, Instance, ParamEnv, Ty, TyCtxt};
|
||||
use syntax_pos::{Span, DUMMY_SP};
|
||||
use rustc::ty::subst::InternalSubsts;
|
||||
|
@ -314,8 +314,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
|||
| HeapAllocNonPowerOfTwoAlignment(_)
|
||||
| Unreachable
|
||||
| ReadFromReturnPointer
|
||||
| GeneratorResumedAfterReturn
|
||||
| GeneratorResumedAfterPanic
|
||||
| ReferencedConstant
|
||||
| InfiniteLoop
|
||||
=> {
|
||||
|
@ -595,7 +593,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
|||
)
|
||||
} else {
|
||||
if overflow {
|
||||
let err = Panic(PanicMessage::Overflow(op)).into();
|
||||
let err = InterpError::Panic(PanicMessage::Overflow(op)).into();
|
||||
let _: Option<()> = self.use_ecx(source_info, |_| Err(err));
|
||||
return None;
|
||||
}
|
||||
|
@ -809,7 +807,7 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
|
|||
self.super_terminator(terminator, location);
|
||||
let source_info = terminator.source_info;
|
||||
match &mut terminator.kind {
|
||||
TerminatorKind::Assert { expected, msg, ref mut cond, .. } => {
|
||||
TerminatorKind::Assert { expected, ref msg, ref mut cond, .. } => {
|
||||
if let Some(value) = self.eval_operand(&cond, source_info) {
|
||||
trace!("assertion on {:?} should be {:?}", value, expected);
|
||||
let expected = ScalarMaybeUndef::from(Scalar::from_bool(*expected));
|
||||
|
@ -831,13 +829,13 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
|
|||
.hir()
|
||||
.as_local_hir_id(self.source.def_id())
|
||||
.expect("some part of a failing const eval must be local");
|
||||
use rustc::mir::interpret::InterpError::*;
|
||||
let msg = match msg {
|
||||
Panic(PanicMessage::Overflow(_)) |
|
||||
Panic(PanicMessage::OverflowNeg) |
|
||||
Panic(PanicMessage::DivisionByZero) |
|
||||
Panic(PanicMessage::RemainderByZero) => msg.description().to_owned(),
|
||||
Panic(PanicMessage::BoundsCheck { ref len, ref index }) => {
|
||||
PanicMessage::Overflow(_) |
|
||||
PanicMessage::OverflowNeg |
|
||||
PanicMessage::DivisionByZero |
|
||||
PanicMessage::RemainderByZero =>
|
||||
msg.description().to_owned(),
|
||||
PanicMessage::BoundsCheck { ref len, ref index } => {
|
||||
let len = self
|
||||
.eval_operand(len, source_info)
|
||||
.expect("len must be const");
|
||||
|
|
|
@ -1016,7 +1016,7 @@ fn create_generator_resume_function<'tcx>(
|
|||
|
||||
let mut cases = create_cases(body, &transform, |point| Some(point.resume));
|
||||
|
||||
use rustc::mir::interpret::InterpError::{
|
||||
use rustc::mir::interpret::PanicMessage::{
|
||||
GeneratorResumedAfterPanic,
|
||||
GeneratorResumedAfterReturn,
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue