From c0420b1a59da4e53aa96b0f7bea6eb43ab7d27f3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 24 Jul 2019 09:12:21 +0200 Subject: [PATCH 1/5] do not use InterpError::description outside librustc::mir --- src/librustc/mir/interpret/error.rs | 2 +- src/librustc_codegen_ssa/mir/block.rs | 4 ++-- src/librustc_mir/transform/const_prop.rs | 5 +++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 6ab07c9679e7a..b5ff55e2f0e99 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -330,7 +330,7 @@ pub enum InterpError<'tcx, O> { pub type InterpResult<'tcx, T = ()> = Result>; impl<'tcx, O> InterpError<'tcx, O> { - pub fn description(&self) -> &str { + pub(crate) fn description(&self) -> &str { use self::InterpError::*; match *self { MachineError(ref inner) => inner, diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index c0a446157d35c..27eddca8542d0 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -418,8 +418,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { vec![file_line_col, index, len]) } _ => { - let str = msg.description(); - let msg_str = LocalInternedString::intern(str); + let str = format!("{:?}", msg); + let msg_str = LocalInternedString::intern(&str); let msg_file_line_col = bx.static_panic_msg( Some(msg_str), filename, diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 37fcd744a3883..1d3d20f298d77 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -809,7 +809,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)); @@ -836,7 +836,8 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { Panic(PanicMessage::Overflow(_)) | Panic(PanicMessage::OverflowNeg) | Panic(PanicMessage::DivisionByZero) | - Panic(PanicMessage::RemainderByZero) => msg.description().to_owned(), + Panic(PanicMessage::RemainderByZero) => + format!("{:?}", msg), Panic(PanicMessage::BoundsCheck { ref len, ref index }) => { let len = self .eval_operand(len, source_info) From 3694d176a20e277581b14a66c530e0565cf05306 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 24 Jul 2019 09:27:20 +0200 Subject: [PATCH 2/5] kill InterpError::description --- src/librustc/mir/interpret/error.rs | 270 ++++++++++++---------------- 1 file changed, 116 insertions(+), 154 deletions(-) diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index b5ff55e2f0e99..4f837241cdd92 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -329,151 +329,6 @@ pub enum InterpError<'tcx, O> { pub type InterpResult<'tcx, T = ()> = Result>; -impl<'tcx, O> InterpError<'tcx, O> { - pub(crate) 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) @@ -516,8 +371,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 +382,130 @@ 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"), + GeneratorResumedAfterReturn => + write!(f, "generator resumed after completion"), + GeneratorResumedAfterPanic => + write!(f, "generator resumed after panicking"), + 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(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), + Panic(PanicMessage::Overflow(mir::BinOp::Add)) => + write!(f, "attempt to add with overflow"), + Panic(PanicMessage::Overflow(mir::BinOp::Sub)) => + write!(f, "attempt to subtract with overflow"), + Panic(PanicMessage::Overflow(mir::BinOp::Mul)) => + write!(f, "attempt to multiply with overflow"), + Panic(PanicMessage::Overflow(mir::BinOp::Div)) => + write!(f, "attempt to divide with overflow"), + Panic(PanicMessage::Overflow(mir::BinOp::Rem)) => + write!(f, "attempt to calculate the remainder with overflow"), + Panic(PanicMessage::OverflowNeg) => + write!(f, "attempt to negate with overflow"), + Panic(PanicMessage::Overflow(mir::BinOp::Shr)) => + write!(f, "attempt to shift right with overflow"), + Panic(PanicMessage::Overflow(mir::BinOp::Shl)) => + write!(f, "attempt to shift left with overflow"), + Panic(PanicMessage::Overflow(op)) => + bug!("{:?} cannot overflow", op), + Panic(PanicMessage::DivisionByZero) => + write!(f, "attempt to divide by zero"), + Panic(PanicMessage::RemainderByZero) => + write!(f, "attempt to calculate the remainder with a divisor of zero"), } } } From 495f9509fe65794384ad62bba90ce742368fdc23 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 24 Jul 2019 10:24:55 +0200 Subject: [PATCH 3/5] use PanicMessage type for MIR assertion errors --- src/librustc/mir/interpret/error.rs | 127 +++++++++++------- src/librustc/mir/mod.rs | 31 +++-- src/librustc/mir/visit.rs | 15 ++- src/librustc_codegen_ssa/mir/block.rs | 10 +- src/librustc_mir/borrow_check/mod.rs | 4 +- .../borrow_check/nll/invalidation.rs | 4 +- .../borrow_check/nll/type_check/mod.rs | 4 +- src/librustc_mir/build/expr/as_place.rs | 6 +- src/librustc_mir/build/expr/as_rvalue.rs | 13 +- src/librustc_mir/interpret/terminator.rs | 35 ++--- src/librustc_mir/transform/const_prop.rs | 19 ++- src/librustc_mir/transform/generator.rs | 2 +- 12 files changed, 155 insertions(+), 115 deletions(-) diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 4f837241cdd92..073ee0028cf43 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -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>, } @@ -185,10 +185,17 @@ 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>, } + +impl<'tcx> fmt::Display for InterpErrorInfo<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.kind) + } +} + impl<'tcx> InterpErrorInfo<'tcx> { pub fn print_backtrace(&mut self) { if let Some(ref mut backtrace) = self.backtrace { @@ -202,8 +209,8 @@ fn print_backtrace(backtrace: &mut Backtrace) { eprintln!("\n\nAn error occurred in miri:\n{:?}", backtrace); } -impl<'tcx> From> for InterpErrorInfo<'tcx> { - fn from(kind: InterpError<'tcx, u64>) -> Self { +impl<'tcx> From> 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> for InterpErrorInfo<'tcx> { } } -pub type AssertMessage<'tcx> = InterpError<'tcx, mir::Operand<'tcx>>; - #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)] pub enum PanicMessage { Panic { @@ -244,10 +249,68 @@ pub enum PanicMessage { OverflowNeg, DivisionByZero, RemainderByZero, + GeneratorResumedAfterReturn, + GeneratorResumedAfterPanic, +} + +/// Type for MIR `Assert` terminator error messages. +pub type AssertMessage<'tcx> = PanicMessage>; + +impl PanicMessage { + /// 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 fmt::Debug for PanicMessage { + 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), + Panic(PanicMessage), ReadFromReturnPointer, PathNotFound(Vec), UnimplementedTraitSelection, @@ -322,28 +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>; -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<'tcx> fmt::Display for InterpError<'tcx> { 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<'tcx> fmt::Debug for InterpError<'tcx> { 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 {}, \ @@ -457,10 +513,6 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for InterpError<'tcx, O> { write!(f, "encountered overly generic constant"), ReferencedConstant => write!(f, "referenced constant has errors"), - GeneratorResumedAfterReturn => - write!(f, "generator resumed after completion"), - GeneratorResumedAfterPanic => - write!(f, "generator resumed after panicking"), InfiniteLoop => write!(f, "duplicate interpreter state observed here, const evaluation will never \ terminate"), @@ -479,33 +531,8 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for InterpError<'tcx, O> { AbiViolation(ref msg) | Intrinsic(ref msg) => write!(f, "{}", msg), - - 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), - Panic(PanicMessage::Overflow(mir::BinOp::Add)) => - write!(f, "attempt to add with overflow"), - Panic(PanicMessage::Overflow(mir::BinOp::Sub)) => - write!(f, "attempt to subtract with overflow"), - Panic(PanicMessage::Overflow(mir::BinOp::Mul)) => - write!(f, "attempt to multiply with overflow"), - Panic(PanicMessage::Overflow(mir::BinOp::Div)) => - write!(f, "attempt to divide with overflow"), - Panic(PanicMessage::Overflow(mir::BinOp::Rem)) => - write!(f, "attempt to calculate the remainder with overflow"), - Panic(PanicMessage::OverflowNeg) => - write!(f, "attempt to negate with overflow"), - Panic(PanicMessage::Overflow(mir::BinOp::Shr)) => - write!(f, "attempt to shift right with overflow"), - Panic(PanicMessage::Overflow(mir::BinOp::Shl)) => - write!(f, "attempt to shift left with overflow"), - Panic(PanicMessage::Overflow(op)) => - bug!("{:?} cannot overflow", op), - Panic(PanicMessage::DivisionByZero) => - write!(f, "attempt to divide by zero"), - Panic(PanicMessage::RemainderByZero) => - write!(f, "attempt to calculate the remainder with a divisor of zero"), + Panic(ref msg) => + write!(f, "{:?}", msg), } } } diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index b1b6be4ae17f8..b3d92e8a604d1 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -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 diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index dca56cc526ce5..7562981f94f61 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -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 + } } } diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 27eddca8542d0..984ff80f03e96 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -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(); @@ -418,8 +418,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { vec![file_line_col, index, len]) } _ => { - let str = format!("{:?}", msg); - let msg_str = LocalInternedString::intern(&str); + let str = msg.description(); + let msg_str = LocalInternedString::intern(str); let msg_file_line_col = bx.static_panic_msg( Some(msg_str), filename, diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 8d27a32a285d8..92285c47db481 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -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); } diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs index 90df0c91c7235..aa9e68bd7de44 100644 --- a/src/librustc_mir/borrow_check/nll/invalidation.rs +++ b/src/librustc_mir/borrow_check/nll/invalidation.rs @@ -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); } diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 6ce2f968ed72d..59a8c8d34d2a1 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -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) } diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs index 42d08a728e0a7..7a428a2ec9f36 100644 --- a/src/librustc_mir/build/expr/as_place.rs +++ b/src/librustc_mir/build/expr/as_place.rs @@ -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)) } diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 8790ebc41693f..92daf06e6f8fe 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -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); diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index a85b77c7b8143..27bd0f8889634 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -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"), }; } } diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 1d3d20f298d77..7a2d78b2e986b 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -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; } @@ -831,14 +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) => - format!("{:?}", msg), - 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"); diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index af412edbdc23f..5461a2e470c7e 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -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, }; From 18551e7d454cae95f51f04a0d4b35f4922bdc120 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 24 Jul 2019 11:43:59 +0200 Subject: [PATCH 4/5] fix unused import --- src/librustc_codegen_ssa/mir/block.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 984ff80f03e96..18611c3e167d2 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -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; From ff187866832784a8fb9d49a8ba45599eb69e171c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 24 Jul 2019 11:45:39 +0200 Subject: [PATCH 5/5] Apply suggestions from code review Co-Authored-By: Mazdak Farrokhzad --- src/librustc/mir/interpret/error.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 073ee0028cf43..5309d5b039e9e 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -190,13 +190,13 @@ pub struct InterpErrorInfo<'tcx> { } -impl<'tcx> fmt::Display for InterpErrorInfo<'tcx> { +impl fmt::Display for InterpErrorInfo<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.kind) } } -impl<'tcx> InterpErrorInfo<'tcx> { +impl InterpErrorInfo<'_> { pub fn print_backtrace(&mut self) { if let Some(ref mut backtrace) = self.backtrace { print_backtrace(&mut *backtrace); @@ -390,14 +390,14 @@ pub enum InterpError<'tcx> { pub type InterpResult<'tcx, T = ()> = Result>; -impl<'tcx> fmt::Display for InterpError<'tcx> { +impl fmt::Display for InterpError<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // Forward `Display` to `Debug` write!(f, "{:?}", self) } } -impl<'tcx> fmt::Debug for InterpError<'tcx> { +impl fmt::Debug for InterpError<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use InterpError::*; match *self {