Skip to content

Commit 82f4a1a

Browse files
committed
get rid of ConstPropUnsupported; use ZST marker structs instead
1 parent 5574b1d commit 82f4a1a

File tree

4 files changed

+63
-24
lines changed

4 files changed

+63
-24
lines changed

src/libcore/any.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ impl dyn Any {
164164
// Get `TypeId` of the type this function is instantiated with.
165165
let t = TypeId::of::<T>();
166166

167-
// Get `TypeId` of the type in the trait object.
167+
// Get `TypeId` of the type in the trait object (`self`).
168168
let concrete = self.type_id();
169169

170170
// Compare both `TypeId`s on equality.

src/librustc/mir/interpret/error.rs

+38-11
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ use rustc_hir as hir;
1414
use rustc_macros::HashStable;
1515
use rustc_session::CtfeBacktrace;
1616
use rustc_span::{def_id::DefId, Pos, Span};
17-
use std::{any::Any, fmt};
17+
use std::{
18+
any::{Any, TypeId},
19+
fmt, mem,
20+
};
1821

1922
#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, RustcEncodable, RustcDecodable)]
2023
pub enum ErrorHandled {
@@ -451,9 +454,6 @@ impl fmt::Debug for UndefinedBehaviorInfo {
451454
pub enum UnsupportedOpInfo {
452455
/// Free-form case. Only for errors that are never caught!
453456
Unsupported(String),
454-
/// When const-prop encounters a situation it does not support, it raises this error.
455-
/// This must not allocate for performance reasons (hence `str`, not `String`).
456-
ConstPropUnsupported(&'static str),
457457
/// Accessing an unsupported foreign static.
458458
ReadForeignStatic(DefId),
459459
/// Could not find MIR for a function.
@@ -472,9 +472,6 @@ impl fmt::Debug for UnsupportedOpInfo {
472472
use UnsupportedOpInfo::*;
473473
match self {
474474
Unsupported(ref msg) => write!(f, "{}", msg),
475-
ConstPropUnsupported(ref msg) => {
476-
write!(f, "Constant propagation encountered an unsupported situation: {}", msg)
477-
}
478475
ReadForeignStatic(did) => {
479476
write!(f, "tried to read from foreign (extern) static {:?}", did)
480477
}
@@ -516,6 +513,35 @@ impl fmt::Debug for ResourceExhaustionInfo {
516513
}
517514
}
518515

516+
/// A trait for machine-specific errors (or other "machine stop" conditions).
517+
pub trait MachineStopType: Any + fmt::Debug + Send {}
518+
impl MachineStopType for String {}
519+
520+
// Copy-pasted from `any.rs`; there does not seem to be a way to re-use that.
521+
impl dyn MachineStopType {
522+
pub fn is<T: Any>(&self) -> bool {
523+
// Get `TypeId` of the type this function is instantiated with.
524+
let t = TypeId::of::<T>();
525+
526+
// Get `TypeId` of the type in the trait object (`self`).
527+
let concrete = self.type_id();
528+
529+
// Compare both `TypeId`s on equality.
530+
t == concrete
531+
}
532+
533+
pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
534+
if self.is::<T>() {
535+
// SAFETY: just checked whether we are pointing to the correct type, and we can rely on
536+
// that check for memory safety because `Any` is implemented for all types; no other
537+
// impls can exist as they would conflict with our impl.
538+
unsafe { Some(&*(self as *const dyn MachineStopType as *const T)) }
539+
} else {
540+
None
541+
}
542+
}
543+
}
544+
519545
pub enum InterpError<'tcx> {
520546
/// The program caused undefined behavior.
521547
UndefinedBehavior(UndefinedBehaviorInfo),
@@ -529,7 +555,7 @@ pub enum InterpError<'tcx> {
529555
ResourceExhaustion(ResourceExhaustionInfo),
530556
/// Stop execution for a machine-controlled reason. This is never raised by
531557
/// the core engine itself.
532-
MachineStop(Box<dyn Any + Send>),
558+
MachineStop(Box<dyn MachineStopType>),
533559
}
534560

535561
pub type InterpResult<'tcx, T = ()> = Result<T, InterpErrorInfo<'tcx>>;
@@ -549,7 +575,7 @@ impl fmt::Debug for InterpError<'_> {
549575
InvalidProgram(ref msg) => write!(f, "{:?}", msg),
550576
UndefinedBehavior(ref msg) => write!(f, "{:?}", msg),
551577
ResourceExhaustion(ref msg) => write!(f, "{:?}", msg),
552-
MachineStop(_) => bug!("unhandled MachineStop"),
578+
MachineStop(ref msg) => write!(f, "{:?}", msg),
553579
}
554580
}
555581
}
@@ -560,8 +586,9 @@ impl InterpError<'_> {
560586
/// waste of resources.
561587
pub fn allocates(&self) -> bool {
562588
match self {
563-
InterpError::MachineStop(_)
564-
| InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_))
589+
// Zero-sized boxes to not allocate.
590+
InterpError::MachineStop(b) => mem::size_of_val(&**b) > 0,
591+
InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_))
565592
| InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationFailure(_))
566593
| InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_))
567594
| InterpError::UndefinedBehavior(UndefinedBehaviorInfo::UbExperimental(_)) => true,

src/librustc/mir/interpret/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,8 @@ mod value;
9292

9393
pub use self::error::{
9494
struct_error, ConstEvalErr, ConstEvalRawResult, ConstEvalResult, ErrorHandled, FrameInfo,
95-
InterpError, InterpErrorInfo, InterpResult, InvalidProgramInfo, ResourceExhaustionInfo,
96-
UndefinedBehaviorInfo, UnsupportedOpInfo,
95+
InterpError, InterpErrorInfo, InterpResult, InvalidProgramInfo, MachineStopType,
96+
ResourceExhaustionInfo, UndefinedBehaviorInfo, UnsupportedOpInfo,
9797
};
9898

9999
pub use self::value::{get_slice_bytes, ConstValue, RawConst, Scalar, ScalarMaybeUndef};

src/librustc_mir/transform/const_prop.rs

+22-10
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
use std::borrow::Cow;
55
use std::cell::Cell;
66

7-
use rustc::mir::interpret::{InterpResult, Scalar};
7+
use rustc::mir::interpret::{InterpResult, MachineStopType, Scalar};
88
use rustc::mir::visit::{
99
MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor,
1010
};
@@ -192,7 +192,10 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
192192
_ret: Option<(PlaceTy<'tcx>, BasicBlock)>,
193193
_unwind: Option<BasicBlock>,
194194
) -> InterpResult<'tcx> {
195-
throw_unsup!(ConstPropUnsupported("calling intrinsics isn't supported in ConstProp"))
195+
#[derive(Debug)]
196+
struct ConstPropIntrinsic;
197+
impl MachineStopType for ConstPropIntrinsic {}
198+
throw_machine_stop!(ConstPropIntrinsic)
196199
}
197200

198201
fn assert_panic(
@@ -204,7 +207,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
204207
}
205208

206209
fn ptr_to_int(_mem: &Memory<'mir, 'tcx, Self>, _ptr: Pointer) -> InterpResult<'tcx, u64> {
207-
throw_unsup!(ConstPropUnsupported("ptr-to-int casts aren't supported in ConstProp"))
210+
throw_unsup!(ReadPointerAsBytes)
208211
}
209212

210213
fn binary_ptr_op(
@@ -213,11 +216,11 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
213216
_left: ImmTy<'tcx>,
214217
_right: ImmTy<'tcx>,
215218
) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> {
219+
#[derive(Debug)]
220+
struct ConstPropPtrOp;
221+
impl MachineStopType for ConstPropPtrOp {}
216222
// We can't do this because aliasing of memory can differ between const eval and llvm
217-
throw_unsup!(ConstPropUnsupported(
218-
"pointer arithmetic or comparisons aren't supported \
219-
in ConstProp"
220-
))
223+
throw_machine_stop!(ConstPropPtrOp)
221224
}
222225

223226
#[inline(always)]
@@ -240,7 +243,10 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
240243
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
241244
_dest: PlaceTy<'tcx>,
242245
) -> InterpResult<'tcx> {
243-
throw_unsup!(ConstPropUnsupported("can't const prop `box` keyword"))
246+
#[derive(Debug)]
247+
struct ConstPropBox;
248+
impl MachineStopType for ConstPropBox {}
249+
throw_machine_stop!(ConstPropBox)
244250
}
245251

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

253259
if l.value == LocalValue::Uninitialized {
254-
throw_unsup!(ConstPropUnsupported("tried to access an uninitialized local"));
260+
#[derive(Debug)]
261+
struct ConstPropUninitLocal;
262+
impl MachineStopType for ConstPropUninitLocal {}
263+
throw_machine_stop!(ConstPropUninitLocal)
255264
}
256265

257266
l.access()
@@ -261,10 +270,13 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
261270
_memory_extra: &(),
262271
allocation: &Allocation<Self::PointerTag, Self::AllocExtra>,
263272
) -> InterpResult<'tcx> {
273+
#[derive(Debug)]
274+
struct ConstPropGlobalMem;
275+
impl MachineStopType for ConstPropGlobalMem {}
264276
// if the static allocation is mutable or if it has relocations (it may be legal to mutate
265277
// the memory behind that in the future), then we can't const prop it
266278
if allocation.mutability == Mutability::Mut || allocation.relocations().len() > 0 {
267-
throw_unsup!(ConstPropUnsupported("can't eval mutable statics in ConstProp"));
279+
throw_machine_stop!(ConstPropGlobalMem)
268280
}
269281

270282
Ok(())

0 commit comments

Comments
 (0)