Skip to content

Commit 495f950

Browse files
committed
use PanicMessage type for MIR assertion errors
1 parent 3694d17 commit 495f950

File tree

12 files changed

+155
-115
lines changed

12 files changed

+155
-115
lines changed

src/librustc/mir/interpret/error.rs

+77-50
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ErrorHandled>;
4747
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
4848
pub struct ConstEvalErr<'tcx> {
4949
pub span: Span,
50-
pub error: crate::mir::interpret::InterpError<'tcx, u64>,
50+
pub error: crate::mir::interpret::InterpError<'tcx>,
5151
pub stacktrace: Vec<FrameInfo<'tcx>>,
5252
}
5353

@@ -185,10 +185,17 @@ pub fn struct_error<'tcx>(tcx: TyCtxtAt<'tcx>, msg: &str) -> DiagnosticBuilder<'
185185
/// macro for this.
186186
#[derive(Debug, Clone)]
187187
pub struct InterpErrorInfo<'tcx> {
188-
pub kind: InterpError<'tcx, u64>,
188+
pub kind: InterpError<'tcx>,
189189
backtrace: Option<Box<Backtrace>>,
190190
}
191191

192+
193+
impl<'tcx> fmt::Display for InterpErrorInfo<'tcx> {
194+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
195+
write!(f, "{}", self.kind)
196+
}
197+
}
198+
192199
impl<'tcx> InterpErrorInfo<'tcx> {
193200
pub fn print_backtrace(&mut self) {
194201
if let Some(ref mut backtrace) = self.backtrace {
@@ -202,8 +209,8 @@ fn print_backtrace(backtrace: &mut Backtrace) {
202209
eprintln!("\n\nAn error occurred in miri:\n{:?}", backtrace);
203210
}
204211

205-
impl<'tcx> From<InterpError<'tcx, u64>> for InterpErrorInfo<'tcx> {
206-
fn from(kind: InterpError<'tcx, u64>) -> Self {
212+
impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
213+
fn from(kind: InterpError<'tcx>) -> Self {
207214
let backtrace = match env::var("RUST_CTFE_BACKTRACE") {
208215
// Matching `RUST_BACKTRACE` -- we treat "0" the same as "not present".
209216
Ok(ref val) if val != "0" => {
@@ -226,8 +233,6 @@ impl<'tcx> From<InterpError<'tcx, u64>> for InterpErrorInfo<'tcx> {
226233
}
227234
}
228235

229-
pub type AssertMessage<'tcx> = InterpError<'tcx, mir::Operand<'tcx>>;
230-
231236
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
232237
pub enum PanicMessage<O> {
233238
Panic {
@@ -244,10 +249,68 @@ pub enum PanicMessage<O> {
244249
OverflowNeg,
245250
DivisionByZero,
246251
RemainderByZero,
252+
GeneratorResumedAfterReturn,
253+
GeneratorResumedAfterPanic,
254+
}
255+
256+
/// Type for MIR `Assert` terminator error messages.
257+
pub type AssertMessage<'tcx> = PanicMessage<mir::Operand<'tcx>>;
258+
259+
impl<O> PanicMessage<O> {
260+
/// Getting a description does not require `O` to be printable, and does not
261+
/// require allocation.
262+
/// The caller is expected to handle `Panic` and `BoundsCheck` separately.
263+
pub fn description(&self) -> &'static str {
264+
use PanicMessage::*;
265+
match self {
266+
Overflow(mir::BinOp::Add) =>
267+
"attempt to add with overflow",
268+
Overflow(mir::BinOp::Sub) =>
269+
"attempt to subtract with overflow",
270+
Overflow(mir::BinOp::Mul) =>
271+
"attempt to multiply with overflow",
272+
Overflow(mir::BinOp::Div) =>
273+
"attempt to divide with overflow",
274+
Overflow(mir::BinOp::Rem) =>
275+
"attempt to calculate the remainder with overflow",
276+
OverflowNeg =>
277+
"attempt to negate with overflow",
278+
Overflow(mir::BinOp::Shr) =>
279+
"attempt to shift right with overflow",
280+
Overflow(mir::BinOp::Shl) =>
281+
"attempt to shift left with overflow",
282+
Overflow(op) =>
283+
bug!("{:?} cannot overflow", op),
284+
DivisionByZero =>
285+
"attempt to divide by zero",
286+
RemainderByZero =>
287+
"attempt to calculate the remainder with a divisor of zero",
288+
GeneratorResumedAfterReturn =>
289+
"generator resumed after completion",
290+
GeneratorResumedAfterPanic =>
291+
"generator resumed after panicking",
292+
Panic { .. } | BoundsCheck { .. } =>
293+
bug!("Unexpected PanicMessage"),
294+
}
295+
}
296+
}
297+
298+
impl<O: fmt::Debug> fmt::Debug for PanicMessage<O> {
299+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
300+
use PanicMessage::*;
301+
match self {
302+
Panic { ref msg, line, col, ref file } =>
303+
write!(f, "the evaluated program panicked at '{}', {}:{}:{}", msg, file, line, col),
304+
BoundsCheck { ref len, ref index } =>
305+
write!(f, "index out of bounds: the len is {:?} but the index is {:?}", len, index),
306+
_ =>
307+
write!(f, "{}", self.description()),
308+
}
309+
}
247310
}
248311

249312
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
250-
pub enum InterpError<'tcx, O> {
313+
pub enum InterpError<'tcx> {
251314
/// This variant is used by machines to signal their own errors that do not
252315
/// match an existing variant.
253316
MachineError(String),
@@ -311,7 +374,7 @@ pub enum InterpError<'tcx, O> {
311374
HeapAllocZeroBytes,
312375
HeapAllocNonPowerOfTwoAlignment(u64),
313376
Unreachable,
314-
Panic(PanicMessage<O>),
377+
Panic(PanicMessage<u64>),
315378
ReadFromReturnPointer,
316379
PathNotFound(Vec<String>),
317380
UnimplementedTraitSelection,
@@ -322,28 +385,21 @@ pub enum InterpError<'tcx, O> {
322385
/// Cannot compute this constant because it depends on another one
323386
/// which already produced an error
324387
ReferencedConstant,
325-
GeneratorResumedAfterReturn,
326-
GeneratorResumedAfterPanic,
327388
InfiniteLoop,
328389
}
329390

330391
pub type InterpResult<'tcx, T = ()> = Result<T, InterpErrorInfo<'tcx>>;
331392

332-
impl<'tcx> fmt::Display for InterpErrorInfo<'tcx> {
333-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
334-
write!(f, "{}", self.kind)
335-
}
336-
}
337-
338-
impl<'tcx> fmt::Display for InterpError<'tcx, u64> {
393+
impl<'tcx> fmt::Display for InterpError<'tcx> {
339394
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
395+
// Forward `Display` to `Debug`
340396
write!(f, "{:?}", self)
341397
}
342398
}
343399

344-
impl<'tcx, O: fmt::Debug> fmt::Debug for InterpError<'tcx, O> {
400+
impl<'tcx> fmt::Debug for InterpError<'tcx> {
345401
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
346-
use self::InterpError::*;
402+
use InterpError::*;
347403
match *self {
348404
PointerOutOfBounds { ptr, msg, allocation_size } => {
349405
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> {
457513
write!(f, "encountered overly generic constant"),
458514
ReferencedConstant =>
459515
write!(f, "referenced constant has errors"),
460-
GeneratorResumedAfterReturn =>
461-
write!(f, "generator resumed after completion"),
462-
GeneratorResumedAfterPanic =>
463-
write!(f, "generator resumed after panicking"),
464516
InfiniteLoop =>
465517
write!(f, "duplicate interpreter state observed here, const evaluation will never \
466518
terminate"),
@@ -479,33 +531,8 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for InterpError<'tcx, O> {
479531
AbiViolation(ref msg) |
480532
Intrinsic(ref msg) =>
481533
write!(f, "{}", msg),
482-
483-
Panic(PanicMessage::Panic { ref msg, line, col, ref file }) =>
484-
write!(f, "the evaluated program panicked at '{}', {}:{}:{}", msg, file, line, col),
485-
Panic(PanicMessage::BoundsCheck { ref len, ref index }) =>
486-
write!(f, "index out of bounds: the len is {:?} but the index is {:?}", len, index),
487-
Panic(PanicMessage::Overflow(mir::BinOp::Add)) =>
488-
write!(f, "attempt to add with overflow"),
489-
Panic(PanicMessage::Overflow(mir::BinOp::Sub)) =>
490-
write!(f, "attempt to subtract with overflow"),
491-
Panic(PanicMessage::Overflow(mir::BinOp::Mul)) =>
492-
write!(f, "attempt to multiply with overflow"),
493-
Panic(PanicMessage::Overflow(mir::BinOp::Div)) =>
494-
write!(f, "attempt to divide with overflow"),
495-
Panic(PanicMessage::Overflow(mir::BinOp::Rem)) =>
496-
write!(f, "attempt to calculate the remainder with overflow"),
497-
Panic(PanicMessage::OverflowNeg) =>
498-
write!(f, "attempt to negate with overflow"),
499-
Panic(PanicMessage::Overflow(mir::BinOp::Shr)) =>
500-
write!(f, "attempt to shift right with overflow"),
501-
Panic(PanicMessage::Overflow(mir::BinOp::Shl)) =>
502-
write!(f, "attempt to shift left with overflow"),
503-
Panic(PanicMessage::Overflow(op)) =>
504-
bug!("{:?} cannot overflow", op),
505-
Panic(PanicMessage::DivisionByZero) =>
506-
write!(f, "attempt to divide by zero"),
507-
Panic(PanicMessage::RemainderByZero) =>
508-
write!(f, "attempt to calculate the remainder with a divisor of zero"),
534+
Panic(ref msg) =>
535+
write!(f, "{:?}", msg),
509536
}
510537
}
511538
}

src/librustc/mir/mod.rs

+19-12
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use crate::hir::def::{CtorKind, Namespace};
88
use crate::hir::def_id::DefId;
99
use crate::hir::{self, InlineAsm as HirInlineAsm};
10-
use crate::mir::interpret::{ConstValue, PanicMessage, InterpError::Panic, Scalar};
10+
use crate::mir::interpret::{ConstValue, PanicMessage, Scalar};
1111
use crate::mir::visit::MirVisitable;
1212
use crate::rustc_serialize as serialize;
1313
use crate::ty::adjustment::PointerCast;
@@ -3152,13 +3152,16 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
31523152
}
31533153
}
31543154
Assert { ref cond, expected, ref msg, target, cleanup } => {
3155-
let msg = if let Panic(PanicMessage::BoundsCheck { ref len, ref index }) = *msg {
3156-
Panic(PanicMessage::BoundsCheck {
3157-
len: len.fold_with(folder),
3158-
index: index.fold_with(folder),
3159-
})
3160-
} else {
3161-
msg.clone()
3155+
use PanicMessage::*;
3156+
let msg = match msg {
3157+
BoundsCheck { ref len, ref index } =>
3158+
BoundsCheck {
3159+
len: len.fold_with(folder),
3160+
index: index.fold_with(folder),
3161+
},
3162+
Panic { .. } | Overflow(_) | OverflowNeg | DivisionByZero | RemainderByZero |
3163+
GeneratorResumedAfterReturn | GeneratorResumedAfterPanic =>
3164+
msg.clone(),
31623165
};
31633166
Assert { cond: cond.fold_with(folder), expected, msg, target, cleanup }
31643167
}
@@ -3197,10 +3200,14 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
31973200
}
31983201
Assert { ref cond, ref msg, .. } => {
31993202
if cond.visit_with(visitor) {
3200-
if let Panic(PanicMessage::BoundsCheck { ref len, ref index }) = *msg {
3201-
len.visit_with(visitor) || index.visit_with(visitor)
3202-
} else {
3203-
false
3203+
use PanicMessage::*;
3204+
match msg {
3205+
BoundsCheck { ref len, ref index } =>
3206+
len.visit_with(visitor) || index.visit_with(visitor),
3207+
Panic { .. } | Overflow(_) | OverflowNeg |
3208+
DivisionByZero | RemainderByZero |
3209+
GeneratorResumedAfterReturn | GeneratorResumedAfterPanic =>
3210+
false
32043211
}
32053212
} else {
32063213
false

src/librustc/mir/visit.rs

+10-5
Original file line numberDiff line numberDiff line change
@@ -514,11 +514,16 @@ macro_rules! make_mir_visitor {
514514
fn super_assert_message(&mut self,
515515
msg: & $($mutability)? AssertMessage<'tcx>,
516516
location: Location) {
517-
use crate::mir::interpret::InterpError::*;
518-
use crate::mir::interpret::PanicMessage::BoundsCheck;
519-
if let Panic(BoundsCheck { len, index }) = msg {
520-
self.visit_operand(len, location);
521-
self.visit_operand(index, location);
517+
use crate::mir::interpret::PanicMessage::*;
518+
match msg {
519+
BoundsCheck { len, index } => {
520+
self.visit_operand(len, location);
521+
self.visit_operand(index, location);
522+
}
523+
Panic { .. } | Overflow(_) | OverflowNeg | DivisionByZero | RemainderByZero |
524+
GeneratorResumedAfterReturn | GeneratorResumedAfterPanic => {
525+
// Nothing to visit
526+
}
522527
}
523528
}
524529

src/librustc_codegen_ssa/mir/block.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
368368
// checked operation, just a comparison with the minimum
369369
// value, so we have to check for the assert message.
370370
if !bx.check_overflow() {
371-
if let InterpError::Panic(PanicMessage::OverflowNeg) = *msg {
371+
if let PanicMessage::OverflowNeg = *msg {
372372
const_cond = Some(expected);
373373
}
374374
}
@@ -402,8 +402,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
402402
let col = bx.const_u32(loc.col.to_usize() as u32 + 1);
403403

404404
// Put together the arguments to the panic entry point.
405-
let (lang_item, args) = match *msg {
406-
InterpError::Panic(PanicMessage::BoundsCheck { ref len, ref index }) => {
405+
let (lang_item, args) = match msg {
406+
PanicMessage::BoundsCheck { ref len, ref index } => {
407407
let len = self.codegen_operand(&mut bx, len).immediate();
408408
let index = self.codegen_operand(&mut bx, index).immediate();
409409

@@ -418,8 +418,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
418418
vec![file_line_col, index, len])
419419
}
420420
_ => {
421-
let str = format!("{:?}", msg);
422-
let msg_str = LocalInternedString::intern(&str);
421+
let str = msg.description();
422+
let msg_str = LocalInternedString::intern(str);
423423
let msg_file_line_col = bx.static_panic_msg(
424424
Some(msg_str),
425425
filename,

src/librustc_mir/borrow_check/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -733,8 +733,8 @@ impl<'cx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tcx
733733
cleanup: _,
734734
} => {
735735
self.consume_operand(loc, (cond, span), flow_state);
736-
use rustc::mir::interpret::{InterpError::Panic, PanicMessage};
737-
if let Panic(PanicMessage::BoundsCheck { ref len, ref index }) = *msg {
736+
use rustc::mir::interpret::PanicMessage;
737+
if let PanicMessage::BoundsCheck { ref len, ref index } = *msg {
738738
self.consume_operand(loc, (len, span), flow_state);
739739
self.consume_operand(loc, (index, span), flow_state);
740740
}

src/librustc_mir/borrow_check/nll/invalidation.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -207,8 +207,8 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
207207
cleanup: _,
208208
} => {
209209
self.consume_operand(location, cond);
210-
use rustc::mir::interpret::{InterpError::Panic, PanicMessage::BoundsCheck};
211-
if let Panic(BoundsCheck { ref len, ref index }) = *msg {
210+
use rustc::mir::interpret::PanicMessage;
211+
if let PanicMessage::BoundsCheck { ref len, ref index } = *msg {
212212
self.consume_operand(location, len);
213213
self.consume_operand(location, index);
214214
}

src/librustc_mir/borrow_check/nll/type_check/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use rustc::infer::canonical::QueryRegionConstraints;
2828
use rustc::infer::outlives::env::RegionBoundPairs;
2929
use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin};
3030
use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
31-
use rustc::mir::interpret::{InterpError::Panic, ConstValue, PanicMessage};
31+
use rustc::mir::interpret::{ConstValue, PanicMessage};
3232
use rustc::mir::tcx::PlaceTy;
3333
use rustc::mir::visit::{PlaceContext, Visitor, NonMutatingUseContext};
3434
use rustc::mir::*;
@@ -1606,7 +1606,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
16061606
span_mirbug!(self, term, "bad Assert ({:?}, not bool", cond_ty);
16071607
}
16081608

1609-
if let Panic(PanicMessage::BoundsCheck { ref len, ref index }) = *msg {
1609+
if let PanicMessage::BoundsCheck { ref len, ref index } = *msg {
16101610
if len.ty(body, tcx) != tcx.types.usize {
16111611
span_mirbug!(self, len, "bounds-check length non-usize {:?}", len)
16121612
}

src/librustc_mir/build/expr/as_place.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::build::expr::category::Category;
44
use crate::build::ForGuard::{OutsideGuard, RefWithinGuard};
55
use crate::build::{BlockAnd, BlockAndExtension, Builder};
66
use crate::hair::*;
7-
use rustc::mir::interpret::{InterpError::Panic, PanicMessage::BoundsCheck};
7+
use rustc::mir::interpret::{PanicMessage::BoundsCheck};
88
use rustc::mir::*;
99
use rustc::ty::{CanonicalUserTypeAnnotation, Variance};
1010

@@ -105,10 +105,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
105105
),
106106
);
107107

108-
let msg = Panic(BoundsCheck {
108+
let msg = BoundsCheck {
109109
len: Operand::Move(len),
110110
index: Operand::Copy(Place::from(idx)),
111-
});
111+
};
112112
let success = this.assert(block, Operand::Move(lt), true, msg, expr_span);
113113
success.and(slice.index(idx))
114114
}

0 commit comments

Comments
 (0)