Skip to content

Commit 51dc78e

Browse files
authored
Rollup merge of #62969 - saleemjaffer:declutter_interperror, r=RalfJung
Changing the structure of `mir::interpret::InterpError` Implements [this](rust-lang/const-eval#4 (comment))
2 parents 6b951c2 + 00d32e8 commit 51dc78e

30 files changed

+440
-380
lines changed

src/librustc/mir/interpret/allocation.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -235,17 +235,17 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
235235
{
236236
assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes());
237237
let offset = ptr.offset.bytes() as usize;
238-
match self.bytes[offset..].iter().position(|&c| c == 0) {
238+
Ok(match self.bytes[offset..].iter().position(|&c| c == 0) {
239239
Some(size) => {
240240
let size_with_null = Size::from_bytes((size + 1) as u64);
241241
// Go through `get_bytes` for checks and AllocationExtra hooks.
242242
// We read the null, so we include it in the request, but we want it removed
243243
// from the result, so we do subslicing.
244-
Ok(&self.get_bytes(cx, ptr, size_with_null)?[..size])
244+
&self.get_bytes(cx, ptr, size_with_null)?[..size]
245245
}
246246
// This includes the case where `offset` is out-of-bounds to begin with.
247-
None => err!(UnterminatedCString(ptr.erase_tag())),
248-
}
247+
None => throw_unsup!(UnterminatedCString(ptr.erase_tag())),
248+
})
249249
}
250250

251251
/// Validates that `ptr.offset` and `ptr.offset + size` do not point to the middle of a
@@ -446,7 +446,7 @@ impl<'tcx, Tag: Copy, Extra> Allocation<Tag, Extra> {
446446
if self.relocations(cx, ptr, size).is_empty() {
447447
Ok(())
448448
} else {
449-
err!(ReadPointerAsBytes)
449+
throw_unsup!(ReadPointerAsBytes)
450450
}
451451
}
452452

@@ -516,7 +516,7 @@ impl<'tcx, Tag, Extra> Allocation<Tag, Extra> {
516516
self.undef_mask.is_range_defined(
517517
ptr.offset,
518518
ptr.offset + size,
519-
).or_else(|idx| err!(ReadUndefBytes(idx)))
519+
).or_else(|idx| throw_unsup!(ReadUndefBytes(idx)))
520520
}
521521

522522
pub fn mark_definedness(

src/librustc/mir/interpret/error.rs

+144-66
Original file line numberDiff line numberDiff line change
@@ -138,10 +138,12 @@ impl<'tcx> ConstEvalErr<'tcx> {
138138
lint_root: Option<hir::HirId>,
139139
) -> Result<DiagnosticBuilder<'tcx>, ErrorHandled> {
140140
match self.error {
141-
InterpError::Layout(LayoutError::Unknown(_)) |
142-
InterpError::TooGeneric => return Err(ErrorHandled::TooGeneric),
143-
InterpError::Layout(LayoutError::SizeOverflow(_)) |
144-
InterpError::TypeckError => return Err(ErrorHandled::Reported),
141+
err_inval!(Layout(LayoutError::Unknown(_))) |
142+
err_inval!(TooGeneric) =>
143+
return Err(ErrorHandled::TooGeneric),
144+
err_inval!(Layout(LayoutError::SizeOverflow(_))) |
145+
err_inval!(TypeckError) =>
146+
return Err(ErrorHandled::Reported),
145147
_ => {},
146148
}
147149
trace!("reporting const eval failure at {:?}", self.span);
@@ -181,8 +183,8 @@ pub fn struct_error<'tcx>(tcx: TyCtxtAt<'tcx>, msg: &str) -> DiagnosticBuilder<'
181183
/// Packages the kind of error we got from the const code interpreter
182184
/// up with a Rust-level backtrace of where the error occured.
183185
/// Thsese should always be constructed by calling `.into()` on
184-
/// a `InterpError`. In `librustc_mir::interpret`, we have the `err!`
185-
/// macro for this.
186+
/// a `InterpError`. In `librustc_mir::interpret`, we have `throw_err_*`
187+
/// macros for this.
186188
#[derive(Debug, Clone)]
187189
pub struct InterpErrorInfo<'tcx> {
188190
pub kind: InterpError<'tcx>,
@@ -234,7 +236,7 @@ impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
234236
}
235237

236238
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
237-
pub enum PanicMessage<O> {
239+
pub enum PanicInfo<O> {
238240
Panic {
239241
msg: Symbol,
240242
line: u32,
@@ -254,14 +256,14 @@ pub enum PanicMessage<O> {
254256
}
255257

256258
/// Type for MIR `Assert` terminator error messages.
257-
pub type AssertMessage<'tcx> = PanicMessage<mir::Operand<'tcx>>;
259+
pub type AssertMessage<'tcx> = PanicInfo<mir::Operand<'tcx>>;
258260

259-
impl<O> PanicMessage<O> {
261+
impl<O> PanicInfo<O> {
260262
/// Getting a description does not require `O` to be printable, and does not
261263
/// require allocation.
262264
/// The caller is expected to handle `Panic` and `BoundsCheck` separately.
263265
pub fn description(&self) -> &'static str {
264-
use PanicMessage::*;
266+
use PanicInfo::*;
265267
match self {
266268
Overflow(mir::BinOp::Add) =>
267269
"attempt to add with overflow",
@@ -290,14 +292,14 @@ impl<O> PanicMessage<O> {
290292
GeneratorResumedAfterPanic =>
291293
"generator resumed after panicking",
292294
Panic { .. } | BoundsCheck { .. } =>
293-
bug!("Unexpected PanicMessage"),
295+
bug!("Unexpected PanicInfo"),
294296
}
295297
}
296298
}
297299

298-
impl<O: fmt::Debug> fmt::Debug for PanicMessage<O> {
300+
impl<O: fmt::Debug> fmt::Debug for PanicInfo<O> {
299301
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
300-
use PanicMessage::*;
302+
use PanicInfo::*;
301303
match self {
302304
Panic { ref msg, line, col, ref file } =>
303305
write!(f, "the evaluated program panicked at '{}', {}:{}:{}", msg, file, line, col),
@@ -310,20 +312,64 @@ impl<O: fmt::Debug> fmt::Debug for PanicMessage<O> {
310312
}
311313

312314
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
313-
pub enum InterpError<'tcx> {
314-
/// This variant is used by machines to signal their own errors that do not
315-
/// match an existing variant.
316-
MachineError(String),
315+
pub enum InvalidProgramInfo<'tcx> {
316+
/// Resolution can fail if we are in a too generic context.
317+
TooGeneric,
318+
/// Cannot compute this constant because it depends on another one
319+
/// which already produced an error.
320+
ReferencedConstant,
321+
/// Abort in case type errors are reached.
322+
TypeckError,
323+
/// An error occurred during layout computation.
324+
Layout(layout::LayoutError<'tcx>),
325+
}
317326

318-
/// Not actually an interpreter error -- used to signal that execution has exited
319-
/// with the given status code. Used by Miri, but not by CTFE.
320-
Exit(i32),
327+
impl fmt::Debug for InvalidProgramInfo<'tcx> {
328+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
329+
use InvalidProgramInfo::*;
330+
match self {
331+
TooGeneric =>
332+
write!(f, "encountered overly generic constant"),
333+
ReferencedConstant =>
334+
write!(f, "referenced constant has errors"),
335+
TypeckError =>
336+
write!(f, "encountered constants with type errors, stopping evaluation"),
337+
Layout(ref err) =>
338+
write!(f, "rustc layout computation failed: {:?}", err),
339+
}
340+
}
341+
}
321342

343+
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
344+
pub enum UndefinedBehaviourInfo {
345+
/// Handle cases which for which we do not have a fixed variant.
346+
Ub(String),
347+
/// Unreachable code was executed.
348+
Unreachable,
349+
}
350+
351+
impl fmt::Debug for UndefinedBehaviourInfo {
352+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
353+
use UndefinedBehaviourInfo::*;
354+
match self {
355+
Ub(ref msg) =>
356+
write!(f, "{}", msg),
357+
Unreachable =>
358+
write!(f, "entered unreachable code"),
359+
}
360+
}
361+
}
362+
363+
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
364+
pub enum UnsupportedOpInfo<'tcx> {
365+
/// Handle cases which for which we do not have a fixed variant.
366+
Unimplemented(String),
367+
368+
// -- Everything below is not classified yet --
322369
FunctionAbiMismatch(Abi, Abi),
323370
FunctionArgMismatch(Ty<'tcx>, Ty<'tcx>),
324371
FunctionRetMismatch(Ty<'tcx>, Ty<'tcx>),
325372
FunctionArgCountMismatch,
326-
NoMirFor(String),
327373
UnterminatedCString(Pointer),
328374
DanglingPointerDeref,
329375
DoubleFree,
@@ -344,12 +390,17 @@ pub enum InterpError<'tcx> {
344390
ReadUndefBytes(Size),
345391
DeadLocal,
346392
InvalidBoolOp(mir::BinOp),
347-
Unimplemented(String),
393+
InlineAsm,
394+
UnimplementedTraitSelection,
395+
CalledClosureAsFunction,
396+
NoMirFor(String),
397+
/// This variant is used by machines to signal their own errors that do not
398+
/// match an existing variant.
399+
MachineError(String),
348400
DerefFunctionPointer,
349401
ExecuteMemory,
350402
Intrinsic(String),
351403
InvalidChar(u128),
352-
StackFrameLimitReached,
353404
OutOfTls,
354405
TlsOutOfBounds,
355406
AbiViolation(String),
@@ -358,49 +409,26 @@ pub enum InterpError<'tcx> {
358409
has: Align,
359410
},
360411
ValidationFailure(String),
361-
CalledClosureAsFunction,
362412
VtableForArgumentlessMethod,
363413
ModifiedConstantMemory,
364414
ModifiedStatic,
365415
AssumptionNotHeld,
366-
InlineAsm,
367416
TypeNotPrimitive(Ty<'tcx>),
368417
ReallocatedWrongMemoryKind(String, String),
369418
DeallocatedWrongMemoryKind(String, String),
370419
ReallocateNonBasePtr,
371420
DeallocateNonBasePtr,
372421
IncorrectAllocationInformation(Size, Size, Align, Align),
373-
Layout(layout::LayoutError<'tcx>),
374422
HeapAllocZeroBytes,
375423
HeapAllocNonPowerOfTwoAlignment(u64),
376-
Unreachable,
377-
Panic(PanicMessage<u64>),
378424
ReadFromReturnPointer,
379425
PathNotFound(Vec<String>),
380-
UnimplementedTraitSelection,
381-
/// Abort in case type errors are reached
382-
TypeckError,
383-
/// Resolution can fail if we are in a too generic context
384-
TooGeneric,
385-
/// Cannot compute this constant because it depends on another one
386-
/// which already produced an error
387-
ReferencedConstant,
388-
InfiniteLoop,
389-
}
390-
391-
pub type InterpResult<'tcx, T = ()> = Result<T, InterpErrorInfo<'tcx>>;
392-
393-
impl fmt::Display for InterpError<'_> {
394-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
395-
// Forward `Display` to `Debug`
396-
write!(f, "{:?}", self)
397-
}
398426
}
399427

400-
impl fmt::Debug for InterpError<'_> {
428+
impl fmt::Debug for UnsupportedOpInfo<'tcx> {
401429
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
402-
use InterpError::*;
403-
match *self {
430+
use UnsupportedOpInfo::*;
431+
match self {
404432
PointerOutOfBounds { ptr, msg, allocation_size } => {
405433
write!(f, "{} failed: pointer must be in-bounds at offset {}, \
406434
but is outside bounds of allocation {} which has size {}",
@@ -434,8 +462,6 @@ impl fmt::Debug for InterpError<'_> {
434462
has.bytes(), required.bytes()),
435463
TypeNotPrimitive(ty) =>
436464
write!(f, "expected primitive type, got {}", ty),
437-
Layout(ref err) =>
438-
write!(f, "rustc layout computation failed: {:?}", err),
439465
PathNotFound(ref path) =>
440466
write!(f, "Cannot find path {:?}", path),
441467
IncorrectAllocationInformation(size, size2, align, align2) =>
@@ -444,8 +470,6 @@ impl fmt::Debug for InterpError<'_> {
444470
size.bytes(), align.bytes(), size2.bytes(), align2.bytes()),
445471
InvalidDiscriminant(val) =>
446472
write!(f, "encountered invalid enum discriminant {}", val),
447-
Exit(code) =>
448-
write!(f, "exited with status code {}", code),
449473
InvalidMemoryAccess =>
450474
write!(f, "tried to access memory through an invalid pointer"),
451475
DanglingPointerDeref =>
@@ -474,8 +498,6 @@ impl fmt::Debug for InterpError<'_> {
474498
write!(f, "tried to dereference a function pointer"),
475499
ExecuteMemory =>
476500
write!(f, "tried to treat a memory pointer as a function pointer"),
477-
StackFrameLimitReached =>
478-
write!(f, "reached the configured maximum number of stack frames"),
479501
OutOfTls =>
480502
write!(f, "reached the maximum number of representable TLS keys"),
481503
TlsOutOfBounds =>
@@ -501,21 +523,10 @@ impl fmt::Debug for InterpError<'_> {
501523
existing object"),
502524
HeapAllocZeroBytes =>
503525
write!(f, "tried to re-, de- or allocate zero bytes on the heap"),
504-
Unreachable =>
505-
write!(f, "entered unreachable code"),
506526
ReadFromReturnPointer =>
507527
write!(f, "tried to read from the return pointer"),
508528
UnimplementedTraitSelection =>
509529
write!(f, "there were unresolved type arguments during trait selection"),
510-
TypeckError =>
511-
write!(f, "encountered constants with type errors, stopping evaluation"),
512-
TooGeneric =>
513-
write!(f, "encountered overly generic constant"),
514-
ReferencedConstant =>
515-
write!(f, "referenced constant has errors"),
516-
InfiniteLoop =>
517-
write!(f, "duplicate interpreter state observed here, const evaluation will never \
518-
terminate"),
519530
InvalidBoolOp(_) =>
520531
write!(f, "invalid boolean operation"),
521532
UnterminatedCString(_) =>
@@ -531,8 +542,75 @@ impl fmt::Debug for InterpError<'_> {
531542
AbiViolation(ref msg) |
532543
Intrinsic(ref msg) =>
533544
write!(f, "{}", msg),
545+
}
546+
}
547+
}
548+
549+
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
550+
pub enum ResourceExhaustionInfo {
551+
/// The stack grew too big.
552+
StackFrameLimitReached,
553+
/// The program ran into an infinite loop.
554+
InfiniteLoop,
555+
}
556+
557+
impl fmt::Debug for ResourceExhaustionInfo {
558+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
559+
use ResourceExhaustionInfo::*;
560+
match self {
561+
StackFrameLimitReached =>
562+
write!(f, "reached the configured maximum number of stack frames"),
563+
InfiniteLoop =>
564+
write!(f, "duplicate interpreter state observed here, const evaluation will never \
565+
terminate"),
566+
}
567+
}
568+
}
569+
570+
#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)]
571+
pub enum InterpError<'tcx> {
572+
/// The program panicked.
573+
Panic(PanicInfo<u64>),
574+
/// The program caused undefined behavior.
575+
UndefinedBehaviour(UndefinedBehaviourInfo),
576+
/// The program did something the interpreter does not support (some of these *might* be UB
577+
/// but the interpreter is not sure).
578+
Unsupported(UnsupportedOpInfo<'tcx>),
579+
/// The program was invalid (ill-typed, not sufficiently monomorphized, ...).
580+
InvalidProgram(InvalidProgramInfo<'tcx>),
581+
/// The program exhausted the interpreter's resources (stack/heap too big,
582+
/// execution takes too long, ..).
583+
ResourceExhaustion(ResourceExhaustionInfo),
584+
/// Not actually an interpreter error -- used to signal that execution has exited
585+
/// with the given status code. Used by Miri, but not by CTFE.
586+
Exit(i32),
587+
}
588+
589+
pub type InterpResult<'tcx, T = ()> = Result<T, InterpErrorInfo<'tcx>>;
590+
591+
impl fmt::Display for InterpError<'_> {
592+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
593+
// Forward `Display` to `Debug`
594+
write!(f, "{:?}", self)
595+
}
596+
}
597+
598+
impl fmt::Debug for InterpError<'_> {
599+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
600+
use InterpError::*;
601+
match *self {
602+
Unsupported(ref msg) =>
603+
write!(f, "{:?}", msg),
604+
InvalidProgram(ref msg) =>
605+
write!(f, "{:?}", msg),
606+
UndefinedBehaviour(ref msg) =>
607+
write!(f, "{:?}", msg),
608+
ResourceExhaustion(ref msg) =>
609+
write!(f, "{:?}", msg),
534610
Panic(ref msg) =>
535611
write!(f, "{:?}", msg),
612+
Exit(code) =>
613+
write!(f, "exited with status code {}", code),
536614
}
537615
}
538616
}

0 commit comments

Comments
 (0)