get rid of ConstPropUnsupported; use ZST marker structs instead
This commit is contained in:
parent
5574b1df57
commit
82f4a1a9b9
4 changed files with 63 additions and 24 deletions
|
@ -164,7 +164,7 @@ impl dyn Any {
|
||||||
// Get `TypeId` of the type this function is instantiated with.
|
// Get `TypeId` of the type this function is instantiated with.
|
||||||
let t = TypeId::of::<T>();
|
let t = TypeId::of::<T>();
|
||||||
|
|
||||||
// Get `TypeId` of the type in the trait object.
|
// Get `TypeId` of the type in the trait object (`self`).
|
||||||
let concrete = self.type_id();
|
let concrete = self.type_id();
|
||||||
|
|
||||||
// Compare both `TypeId`s on equality.
|
// Compare both `TypeId`s on equality.
|
||||||
|
|
|
@ -14,7 +14,10 @@ use rustc_hir as hir;
|
||||||
use rustc_macros::HashStable;
|
use rustc_macros::HashStable;
|
||||||
use rustc_session::CtfeBacktrace;
|
use rustc_session::CtfeBacktrace;
|
||||||
use rustc_span::{def_id::DefId, Pos, Span};
|
use rustc_span::{def_id::DefId, Pos, Span};
|
||||||
use std::{any::Any, fmt};
|
use std::{
|
||||||
|
any::{Any, TypeId},
|
||||||
|
fmt, mem,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, RustcEncodable, RustcDecodable)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, RustcEncodable, RustcDecodable)]
|
||||||
pub enum ErrorHandled {
|
pub enum ErrorHandled {
|
||||||
|
@ -451,9 +454,6 @@ impl fmt::Debug for UndefinedBehaviorInfo {
|
||||||
pub enum UnsupportedOpInfo {
|
pub enum UnsupportedOpInfo {
|
||||||
/// Free-form case. Only for errors that are never caught!
|
/// Free-form case. Only for errors that are never caught!
|
||||||
Unsupported(String),
|
Unsupported(String),
|
||||||
/// When const-prop encounters a situation it does not support, it raises this error.
|
|
||||||
/// This must not allocate for performance reasons (hence `str`, not `String`).
|
|
||||||
ConstPropUnsupported(&'static str),
|
|
||||||
/// Accessing an unsupported foreign static.
|
/// Accessing an unsupported foreign static.
|
||||||
ReadForeignStatic(DefId),
|
ReadForeignStatic(DefId),
|
||||||
/// Could not find MIR for a function.
|
/// Could not find MIR for a function.
|
||||||
|
@ -472,9 +472,6 @@ impl fmt::Debug for UnsupportedOpInfo {
|
||||||
use UnsupportedOpInfo::*;
|
use UnsupportedOpInfo::*;
|
||||||
match self {
|
match self {
|
||||||
Unsupported(ref msg) => write!(f, "{}", msg),
|
Unsupported(ref msg) => write!(f, "{}", msg),
|
||||||
ConstPropUnsupported(ref msg) => {
|
|
||||||
write!(f, "Constant propagation encountered an unsupported situation: {}", msg)
|
|
||||||
}
|
|
||||||
ReadForeignStatic(did) => {
|
ReadForeignStatic(did) => {
|
||||||
write!(f, "tried to read from foreign (extern) static {:?}", did)
|
write!(f, "tried to read from foreign (extern) static {:?}", did)
|
||||||
}
|
}
|
||||||
|
@ -516,6 +513,35 @@ impl fmt::Debug for ResourceExhaustionInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A trait for machine-specific errors (or other "machine stop" conditions).
|
||||||
|
pub trait MachineStopType: Any + fmt::Debug + Send {}
|
||||||
|
impl MachineStopType for String {}
|
||||||
|
|
||||||
|
// Copy-pasted from `any.rs`; there does not seem to be a way to re-use that.
|
||||||
|
impl dyn MachineStopType {
|
||||||
|
pub fn is<T: Any>(&self) -> bool {
|
||||||
|
// Get `TypeId` of the type this function is instantiated with.
|
||||||
|
let t = TypeId::of::<T>();
|
||||||
|
|
||||||
|
// Get `TypeId` of the type in the trait object (`self`).
|
||||||
|
let concrete = self.type_id();
|
||||||
|
|
||||||
|
// Compare both `TypeId`s on equality.
|
||||||
|
t == concrete
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
|
||||||
|
if self.is::<T>() {
|
||||||
|
// SAFETY: just checked whether we are pointing to the correct type, and we can rely on
|
||||||
|
// that check for memory safety because `Any` is implemented for all types; no other
|
||||||
|
// impls can exist as they would conflict with our impl.
|
||||||
|
unsafe { Some(&*(self as *const dyn MachineStopType as *const T)) }
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub enum InterpError<'tcx> {
|
pub enum InterpError<'tcx> {
|
||||||
/// The program caused undefined behavior.
|
/// The program caused undefined behavior.
|
||||||
UndefinedBehavior(UndefinedBehaviorInfo),
|
UndefinedBehavior(UndefinedBehaviorInfo),
|
||||||
|
@ -529,7 +555,7 @@ pub enum InterpError<'tcx> {
|
||||||
ResourceExhaustion(ResourceExhaustionInfo),
|
ResourceExhaustion(ResourceExhaustionInfo),
|
||||||
/// Stop execution for a machine-controlled reason. This is never raised by
|
/// Stop execution for a machine-controlled reason. This is never raised by
|
||||||
/// the core engine itself.
|
/// the core engine itself.
|
||||||
MachineStop(Box<dyn Any + Send>),
|
MachineStop(Box<dyn MachineStopType>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type InterpResult<'tcx, T = ()> = Result<T, InterpErrorInfo<'tcx>>;
|
pub type InterpResult<'tcx, T = ()> = Result<T, InterpErrorInfo<'tcx>>;
|
||||||
|
@ -549,7 +575,7 @@ impl fmt::Debug for InterpError<'_> {
|
||||||
InvalidProgram(ref msg) => write!(f, "{:?}", msg),
|
InvalidProgram(ref msg) => write!(f, "{:?}", msg),
|
||||||
UndefinedBehavior(ref msg) => write!(f, "{:?}", msg),
|
UndefinedBehavior(ref msg) => write!(f, "{:?}", msg),
|
||||||
ResourceExhaustion(ref msg) => write!(f, "{:?}", msg),
|
ResourceExhaustion(ref msg) => write!(f, "{:?}", msg),
|
||||||
MachineStop(_) => bug!("unhandled MachineStop"),
|
MachineStop(ref msg) => write!(f, "{:?}", msg),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -560,8 +586,9 @@ impl InterpError<'_> {
|
||||||
/// waste of resources.
|
/// waste of resources.
|
||||||
pub fn allocates(&self) -> bool {
|
pub fn allocates(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
InterpError::MachineStop(_)
|
// Zero-sized boxes to not allocate.
|
||||||
| InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_))
|
InterpError::MachineStop(b) => mem::size_of_val(&**b) > 0,
|
||||||
|
InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_))
|
||||||
| InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationFailure(_))
|
| InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationFailure(_))
|
||||||
| InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_))
|
| InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_))
|
||||||
| InterpError::UndefinedBehavior(UndefinedBehaviorInfo::UbExperimental(_)) => true,
|
| InterpError::UndefinedBehavior(UndefinedBehaviorInfo::UbExperimental(_)) => true,
|
||||||
|
|
|
@ -92,8 +92,8 @@ mod value;
|
||||||
|
|
||||||
pub use self::error::{
|
pub use self::error::{
|
||||||
struct_error, ConstEvalErr, ConstEvalRawResult, ConstEvalResult, ErrorHandled, FrameInfo,
|
struct_error, ConstEvalErr, ConstEvalRawResult, ConstEvalResult, ErrorHandled, FrameInfo,
|
||||||
InterpError, InterpErrorInfo, InterpResult, InvalidProgramInfo, ResourceExhaustionInfo,
|
InterpError, InterpErrorInfo, InterpResult, InvalidProgramInfo, MachineStopType,
|
||||||
UndefinedBehaviorInfo, UnsupportedOpInfo,
|
ResourceExhaustionInfo, UndefinedBehaviorInfo, UnsupportedOpInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use self::value::{get_slice_bytes, ConstValue, RawConst, Scalar, ScalarMaybeUndef};
|
pub use self::value::{get_slice_bytes, ConstValue, RawConst, Scalar, ScalarMaybeUndef};
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
|
|
||||||
use rustc::mir::interpret::{InterpResult, Scalar};
|
use rustc::mir::interpret::{InterpResult, MachineStopType, Scalar};
|
||||||
use rustc::mir::visit::{
|
use rustc::mir::visit::{
|
||||||
MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor,
|
MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor,
|
||||||
};
|
};
|
||||||
|
@ -192,7 +192,10 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
|
||||||
_ret: Option<(PlaceTy<'tcx>, BasicBlock)>,
|
_ret: Option<(PlaceTy<'tcx>, BasicBlock)>,
|
||||||
_unwind: Option<BasicBlock>,
|
_unwind: Option<BasicBlock>,
|
||||||
) -> InterpResult<'tcx> {
|
) -> InterpResult<'tcx> {
|
||||||
throw_unsup!(ConstPropUnsupported("calling intrinsics isn't supported in ConstProp"))
|
#[derive(Debug)]
|
||||||
|
struct ConstPropIntrinsic;
|
||||||
|
impl MachineStopType for ConstPropIntrinsic {}
|
||||||
|
throw_machine_stop!(ConstPropIntrinsic)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assert_panic(
|
fn assert_panic(
|
||||||
|
@ -204,7 +207,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ptr_to_int(_mem: &Memory<'mir, 'tcx, Self>, _ptr: Pointer) -> InterpResult<'tcx, u64> {
|
fn ptr_to_int(_mem: &Memory<'mir, 'tcx, Self>, _ptr: Pointer) -> InterpResult<'tcx, u64> {
|
||||||
throw_unsup!(ConstPropUnsupported("ptr-to-int casts aren't supported in ConstProp"))
|
throw_unsup!(ReadPointerAsBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn binary_ptr_op(
|
fn binary_ptr_op(
|
||||||
|
@ -213,11 +216,11 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
|
||||||
_left: ImmTy<'tcx>,
|
_left: ImmTy<'tcx>,
|
||||||
_right: ImmTy<'tcx>,
|
_right: ImmTy<'tcx>,
|
||||||
) -> InterpResult<'tcx, (Scalar, bool, Ty<'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
|
// We can't do this because aliasing of memory can differ between const eval and llvm
|
||||||
throw_unsup!(ConstPropUnsupported(
|
throw_machine_stop!(ConstPropPtrOp)
|
||||||
"pointer arithmetic or comparisons aren't supported \
|
|
||||||
in ConstProp"
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -240,7 +243,10 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
|
||||||
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||||
_dest: PlaceTy<'tcx>,
|
_dest: PlaceTy<'tcx>,
|
||||||
) -> InterpResult<'tcx> {
|
) -> InterpResult<'tcx> {
|
||||||
throw_unsup!(ConstPropUnsupported("can't const prop `box` keyword"))
|
#[derive(Debug)]
|
||||||
|
struct ConstPropBox;
|
||||||
|
impl MachineStopType for ConstPropBox {}
|
||||||
|
throw_machine_stop!(ConstPropBox)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn access_local(
|
fn access_local(
|
||||||
|
@ -251,7 +257,10 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
|
||||||
let l = &frame.locals[local];
|
let l = &frame.locals[local];
|
||||||
|
|
||||||
if l.value == LocalValue::Uninitialized {
|
if l.value == LocalValue::Uninitialized {
|
||||||
throw_unsup!(ConstPropUnsupported("tried to access an uninitialized local"));
|
#[derive(Debug)]
|
||||||
|
struct ConstPropUninitLocal;
|
||||||
|
impl MachineStopType for ConstPropUninitLocal {}
|
||||||
|
throw_machine_stop!(ConstPropUninitLocal)
|
||||||
}
|
}
|
||||||
|
|
||||||
l.access()
|
l.access()
|
||||||
|
@ -261,10 +270,13 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
|
||||||
_memory_extra: &(),
|
_memory_extra: &(),
|
||||||
allocation: &Allocation<Self::PointerTag, Self::AllocExtra>,
|
allocation: &Allocation<Self::PointerTag, Self::AllocExtra>,
|
||||||
) -> InterpResult<'tcx> {
|
) -> 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
|
// 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
|
// the memory behind that in the future), then we can't const prop it
|
||||||
if allocation.mutability == Mutability::Mut || allocation.relocations().len() > 0 {
|
if allocation.mutability == Mutability::Mut || allocation.relocations().len() > 0 {
|
||||||
throw_unsup!(ConstPropUnsupported("can't eval mutable statics in ConstProp"));
|
throw_machine_stop!(ConstPropGlobalMem)
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue