about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2020-03-23 10:58:43 +0100
committerRalf Jung <post@ralfj.de>2020-03-23 11:02:18 +0100
commit410385dfd0532f3e8867afaaa4b89c315b0e84b1 (patch)
treecc840208cdfb6ae47c78ed94914a0eb673df3f08
parentcda81da6ea4c037ef036067d9cb98e80208ee525 (diff)
downloadrust-410385dfd0532f3e8867afaaa4b89c315b0e84b1.tar.gz
rust-410385dfd0532f3e8867afaaa4b89c315b0e84b1.zip
add macro to reduce boilerplate and keep readable messages
-rw-r--r--src/librustc/mir/interpret/error.rs2
-rw-r--r--src/librustc_mir/transform/const_prop.rs45
2 files changed, 25 insertions, 22 deletions
diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs
index d00eb7921a0..010b73db9ac 100644
--- a/src/librustc/mir/interpret/error.rs
+++ b/src/librustc/mir/interpret/error.rs
@@ -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(_))
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index 687bacfdc1b..74140a1fc6d 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -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,
 };
@@ -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 {
@@ -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(
@@ -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)]
@@ -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(
@@ -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()
@@ -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(())