Skip to content

Commit

Permalink
add macro to reduce boilerplate and keep readable messages
Browse files Browse the repository at this point in the history
  • Loading branch information
RalfJung committed Mar 23, 2020
1 parent cda81da commit 410385d
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 22 deletions.
2 changes: 1 addition & 1 deletion src/librustc/mir/interpret/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -577,7 +577,7 @@ impl InterpError<'_> {
/// waste of resources.
pub fn allocates(&self) -> bool {
match self {
// Zero-sized boxes to not allocate.
// Zero-sized boxes do not allocate.
InterpError::MachineStop(b) => mem::size_of_val(&**b) > 0,
InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_))
| InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationFailure(_))
Expand Down
45 changes: 24 additions & 21 deletions src/librustc_mir/transform/const_prop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
use std::borrow::Cow;
use std::cell::Cell;

use rustc::mir::interpret::{InterpResult, MachineStopType, Scalar};
use rustc::mir::interpret::{InterpResult, Scalar};
use rustc::mir::visit::{
MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor,
};
Expand Down Expand Up @@ -39,6 +39,24 @@ use crate::transform::{MirPass, MirSource};
/// The maximum number of bytes that we'll allocate space for a return value.
const MAX_ALLOC_LIMIT: u64 = 1024;

/// Macro for machine-specific `InterpError` without allocation.
/// (These will never be shown to the user, but they help diagnose ICEs.)
macro_rules! throw_machine_stop_str {
($($tt:tt)*) => {{
// We make a new local type for it. The type itself does not carry any information,
// but its vtable (for the `MachineStopType` trait) does.
struct Zst;
// Debug-printing this type shows the desired string.
impl std::fmt::Debug for Zst {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, $($tt)*)
}
}
impl rustc::mir::interpret::MachineStopType for Zst {}
throw_machine_stop!(Zst)
}};
}

pub struct ConstProp;

impl<'tcx> MirPass<'tcx> for ConstProp {
Expand Down Expand Up @@ -192,10 +210,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
_ret: Option<(PlaceTy<'tcx>, BasicBlock)>,
_unwind: Option<BasicBlock>,
) -> InterpResult<'tcx> {
#[derive(Debug)]
struct ConstPropIntrinsic;
impl MachineStopType for ConstPropIntrinsic {}
throw_machine_stop!(ConstPropIntrinsic)
throw_machine_stop_str!("calling intrinsics isn't supported in ConstProp")
}

fn assert_panic(
Expand All @@ -216,11 +231,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
_left: ImmTy<'tcx>,
_right: ImmTy<'tcx>,
) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> {
#[derive(Debug)]
struct ConstPropPtrOp;
impl MachineStopType for ConstPropPtrOp {}
// We can't do this because aliasing of memory can differ between const eval and llvm
throw_machine_stop!(ConstPropPtrOp)
throw_machine_stop_str!("pointer arithmetic or comparisons aren't supported in ConstProp")
}

#[inline(always)]
Expand All @@ -243,10 +255,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
_dest: PlaceTy<'tcx>,
) -> InterpResult<'tcx> {
#[derive(Debug)]
struct ConstPropBox;
impl MachineStopType for ConstPropBox {}
throw_machine_stop!(ConstPropBox)
throw_machine_stop_str!("can't const prop heap allocations")
}

fn access_local(
Expand All @@ -257,10 +266,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
let l = &frame.locals[local];

if l.value == LocalValue::Uninitialized {
#[derive(Debug)]
struct ConstPropUninitLocal;
impl MachineStopType for ConstPropUninitLocal {}
throw_machine_stop!(ConstPropUninitLocal)
throw_machine_stop_str!("tried to access an uninitialized local")
}

l.access()
Expand All @@ -270,13 +276,10 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
_memory_extra: &(),
allocation: &Allocation<Self::PointerTag, Self::AllocExtra>,
) -> InterpResult<'tcx> {
#[derive(Debug)]
struct ConstPropGlobalMem;
impl MachineStopType for ConstPropGlobalMem {}
// if the static allocation is mutable or if it has relocations (it may be legal to mutate
// the memory behind that in the future), then we can't const prop it
if allocation.mutability == Mutability::Mut || allocation.relocations().len() > 0 {
throw_machine_stop!(ConstPropGlobalMem)
throw_machine_stop_str!("can't eval mutable statics in ConstProp")
}

Ok(())
Expand Down

0 comments on commit 410385d

Please sign in to comment.