ReadForeignStatic(DefId),
/// Could not find MIR for a function.
NoMirFor(DefId),
- /// Modified a static during const-eval.
- /// FIXME: move this to `ConstEvalErrKind` through a machine hook.
- ModifiedStatic,
/// Encountered a pointer where we needed raw bytes.
ReadPointerAsBytes,
/// Encountered raw bytes where we needed a pointer.
write!(f, "tried to read from foreign (extern) static {:?}", did)
}
NoMirFor(did) => write!(f, "could not load MIR for {:?}", did),
- ModifiedStatic => write!(
- f,
- "tried to modify a static's initial value from another static's \
- initializer"
- ),
-
ReadPointerAsBytes => write!(f, "unable to turn pointer into raw bytes",),
ReadBytesAsPointer => write!(f, "unable to turn bytes into a pointer"),
}
/// Stores the value of constants (and deduplicates the actual memory)
allocation_interner: ShardedHashMap<&'tcx Allocation, ()>,
+ /// Stores memory for globals (statics/consts).
pub alloc_map: Lock<interpret::AllocMap<'tcx>>,
layout_interner: ShardedHashMap<&'tcx LayoutDetails, ()>,
pub enum ConstEvalErrKind {
NeedsRfc(String),
ConstAccessesStatic,
+ ModifiedGlobal,
AssertFailure(AssertKind<u64>),
Panic { msg: Symbol, line: u32, col: u32, file: Symbol },
}
write!(f, "\"{}\" needs an rfc before being allowed inside constants", msg)
}
ConstAccessesStatic => write!(f, "constant accesses static"),
+ ModifiedGlobal => write!(
+ f,
+ "modifying a static's initial value from another static's \
+ initializer"
+ ),
AssertFailure(ref msg) => write!(f, "{:?}", msg),
Panic { msg, line, col, file } => {
write!(f, "the evaluated program panicked at '{}', {}:{}:{}", msg, file, line, col)
use rustc_data_structures::fx::FxHashMap;
use rustc::mir::AssertMessage;
-use rustc_span::source_map::Span;
use rustc_span::symbol::Symbol;
+use rustc_span::{def_id::DefId, Span};
use crate::interpret::{
self, AllocId, Allocation, GlobalId, ImmTy, InterpCx, InterpResult, Memory, MemoryKind, OpTy,
}
impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter {
- type MemoryKinds = !;
+ type MemoryKind = !;
type PointerTag = ();
type ExtraFnVal = !;
type MemoryMap = FxHashMap<AllocId, (MemoryKind<!>, Allocation)>;
- const STATIC_KIND: Option<!> = None; // no copying of statics allowed
+ const GLOBAL_KIND: Option<!> = None; // no copying of globals allowed
// We do not check for alignment to avoid having to carry an `Align`
// in `ConstValue::ByRef`.
}
#[inline(always)]
- fn tag_static_base_pointer(_memory_extra: &MemoryExtra, _id: AllocId) -> Self::PointerTag {}
+ fn tag_global_base_pointer(_memory_extra: &MemoryExtra, _id: AllocId) -> Self::PointerTag {}
fn box_alloc(
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
Ok(())
}
- fn before_access_static(
+ fn before_access_global(
memory_extra: &MemoryExtra,
_allocation: &Allocation,
+ def_id: Option<DefId>,
+ is_write: bool,
) -> InterpResult<'tcx> {
- if memory_extra.can_access_statics {
+ if is_write {
+ Err(ConstEvalErrKind::ModifiedGlobal.into())
+ } else if memory_extra.can_access_statics || def_id.is_none() {
Ok(())
} else {
Err(ConstEvalErrKind::ConstAccessesStatic.into())
/// This represents a *direct* access to that memory, as opposed to access
/// through a pointer that was created by the program.
#[inline(always)]
- pub fn tag_static_base_pointer(&self, ptr: Pointer) -> Pointer<M::PointerTag> {
- self.memory.tag_static_base_pointer(ptr)
+ pub fn tag_global_base_pointer(&self, ptr: Pointer) -> Pointer<M::PointerTag> {
+ self.memory.tag_global_base_pointer(ptr)
}
#[inline(always)]
pub trait CompileTimeMachine<'mir, 'tcx> = Machine<
'mir,
'tcx,
- MemoryKinds = !,
+ MemoryKind = !,
PointerTag = (),
ExtraFnVal = !,
FrameExtra = (),
MemoryKind::Stack | MemoryKind::Vtable | MemoryKind::CallerLocation => {}
}
// Set allocation mutability as appropriate. This is used by LLVM to put things into
- // read-only memory, and also by Miri when evluating other constants/statics that
+ // read-only memory, and also by Miri when evaluating other globals that
// access this one.
if mode == InternMode::Static {
// When `ty` is `None`, we assume no interior mutability.
use rustc::mir;
use rustc::ty::{self, Ty};
-use rustc_span::Span;
+use rustc_span::{def_id::DefId, Span};
use super::{
AllocId, Allocation, AllocationExtra, Frame, ImmTy, InterpCx, InterpResult, Memory, MemoryKind,
/// and some use case dependent behaviour can instead be applied.
pub trait Machine<'mir, 'tcx>: Sized {
/// Additional memory kinds a machine wishes to distinguish from the builtin ones
- type MemoryKinds: ::std::fmt::Debug + MayLeak + Eq + 'static;
+ type MemoryKind: ::std::fmt::Debug + MayLeak + Eq + 'static;
/// Tag tracked alongside every pointer. This is used to implement "Stacked Borrows"
/// <https://www.ralfj.de/blog/2018/08/07/stacked-borrows.html>.
/// Memory's allocation map
type MemoryMap: AllocMap<
AllocId,
- (MemoryKind<Self::MemoryKinds>, Allocation<Self::PointerTag, Self::AllocExtra>),
+ (MemoryKind<Self::MemoryKind>, Allocation<Self::PointerTag, Self::AllocExtra>),
> + Default
+ Clone;
- /// The memory kind to use for copied statics -- or None if statics should not be mutated
- /// and thus any such attempt will cause a `ModifiedStatic` error to be raised.
+ /// The memory kind to use for copied global memory (held in `tcx`) --
+ /// or None if such memory should not be mutated and thus any such attempt will cause
+ /// a `ModifiedStatic` error to be raised.
/// Statics are copied under two circumstances: When they are mutated, and when
- /// `tag_allocation` or `find_foreign_static` (see below) returns an owned allocation
+ /// `tag_allocation` (see below) returns an owned allocation
/// that is added to the memory so that the work is not done twice.
- const STATIC_KIND: Option<Self::MemoryKinds>;
+ const GLOBAL_KIND: Option<Self::MemoryKind>;
/// Whether memory accesses should be alignment-checked.
const CHECK_ALIGN: bool;
Ok(())
}
- /// Called before a `Static` value is accessed.
+ /// Called before a global allocation is accessed.
#[inline]
- fn before_access_static(
+ fn before_access_global(
_memory_extra: &Self::MemoryExtra,
_allocation: &Allocation,
+ _def_id: Option<DefId>,
+ _is_write: bool,
) -> InterpResult<'tcx> {
Ok(())
}
/// it contains (in relocations) tagged. The way we construct allocations is
/// to always first construct it without extra and then add the extra.
/// This keeps uniform code paths for handling both allocations created by CTFE
- /// for statics, and allocations created by Miri during evaluation.
+ /// for globals, and allocations created by Miri during evaluation.
///
/// `kind` is the kind of the allocation being tagged; it can be `None` when
- /// it's a static and `STATIC_KIND` is `None`.
+ /// it's a global and `GLOBAL_KIND` is `None`.
///
/// This should avoid copying if no work has to be done! If this returns an owned
/// allocation (because a copy had to be done to add tags or metadata), machine memory will
///
/// Also return the "base" tag to use for this allocation: the one that is used for direct
/// accesses to this allocation. If `kind == STATIC_KIND`, this tag must be consistent
- /// with `tag_static_base_pointer`.
+ /// with `tag_global_base_pointer`.
fn init_allocation_extra<'b>(
memory_extra: &Self::MemoryExtra,
id: AllocId,
alloc: Cow<'b, Allocation>,
- kind: Option<MemoryKind<Self::MemoryKinds>>,
+ kind: Option<MemoryKind<Self::MemoryKind>>,
) -> (Cow<'b, Allocation<Self::PointerTag, Self::AllocExtra>>, Self::PointerTag);
- /// Return the "base" tag for the given *static* allocation: the one that is used for direct
- /// accesses to this static/const/fn allocation. If `id` is not a static allocation,
+ /// Return the "base" tag for the given *global* allocation: the one that is used for direct
+ /// accesses to this static/const/fn allocation. If `id` is not a global allocation,
/// this will return an unusable tag (i.e., accesses will be UB)!
///
/// Expects `id` to be already canonical, if needed.
- fn tag_static_base_pointer(memory_extra: &Self::MemoryExtra, id: AllocId) -> Self::PointerTag;
+ fn tag_global_base_pointer(memory_extra: &Self::MemoryExtra, id: AllocId) -> Self::PointerTag;
/// Executes a retagging operation
#[inline]
/// Allocations local to this instance of the miri engine. The kind
/// helps ensure that the same mechanism is used for allocation and
/// deallocation. When an allocation is not found here, it is a
- /// static and looked up in the `tcx` for read access. Some machines may
- /// have to mutate this map even on a read-only access to a static (because
+ /// global and looked up in the `tcx` for read access. Some machines may
+ /// have to mutate this map even on a read-only access to a global (because
/// they do pointer provenance tracking and the allocations in `tcx` have
/// the wrong type), so we let the machine override this type.
- /// Either way, if the machine allows writing to a static, doing so will
- /// create a copy of the static allocation here.
+ /// Either way, if the machine allows writing to a global, doing so will
+ /// create a copy of the global allocation here.
// FIXME: this should not be public, but interning currently needs access to it
pub(super) alloc_map: M::MemoryMap,
/// This represents a *direct* access to that memory, as opposed to access
/// through a pointer that was created by the program.
#[inline]
- pub fn tag_static_base_pointer(&self, ptr: Pointer) -> Pointer<M::PointerTag> {
+ pub fn tag_global_base_pointer(&self, ptr: Pointer) -> Pointer<M::PointerTag> {
let id = M::canonical_alloc_id(self, ptr.alloc_id);
- ptr.with_tag(M::tag_static_base_pointer(&self.extra, id))
+ ptr.with_tag(M::tag_global_base_pointer(&self.extra, id))
}
pub fn create_fn_alloc(
id
}
};
- self.tag_static_base_pointer(Pointer::from(id))
+ self.tag_global_base_pointer(Pointer::from(id))
}
pub fn allocate(
&mut self,
size: Size,
align: Align,
- kind: MemoryKind<M::MemoryKinds>,
+ kind: MemoryKind<M::MemoryKind>,
) -> Pointer<M::PointerTag> {
let alloc = Allocation::undef(size, align);
self.allocate_with(alloc, kind)
}
- pub fn allocate_static_bytes(
+ pub fn allocate_bytes(
&mut self,
bytes: &[u8],
- kind: MemoryKind<M::MemoryKinds>,
+ kind: MemoryKind<M::MemoryKind>,
) -> Pointer<M::PointerTag> {
let alloc = Allocation::from_byte_aligned_bytes(bytes);
self.allocate_with(alloc, kind)
pub fn allocate_with(
&mut self,
alloc: Allocation,
- kind: MemoryKind<M::MemoryKinds>,
+ kind: MemoryKind<M::MemoryKind>,
) -> Pointer<M::PointerTag> {
let id = self.tcx.alloc_map.lock().reserve();
debug_assert_ne!(
Some(kind),
- M::STATIC_KIND.map(MemoryKind::Machine),
- "dynamically allocating static memory"
+ M::GLOBAL_KIND.map(MemoryKind::Machine),
+ "dynamically allocating global memory"
);
let (alloc, tag) = M::init_allocation_extra(&self.extra, id, Cow::Owned(alloc), Some(kind));
self.alloc_map.insert(id, (kind, alloc.into_owned()));
old_size_and_align: Option<(Size, Align)>,
new_size: Size,
new_align: Align,
- kind: MemoryKind<M::MemoryKinds>,
+ kind: MemoryKind<M::MemoryKind>,
) -> InterpResult<'tcx, Pointer<M::PointerTag>> {
if ptr.offset.bytes() != 0 {
throw_ub_format!(
Ok(new_ptr)
}
- /// Deallocate a local, or do nothing if that local has been made into a static
+ /// Deallocate a local, or do nothing if that local has been made into a global.
pub fn deallocate_local(&mut self, ptr: Pointer<M::PointerTag>) -> InterpResult<'tcx> {
- // The allocation might be already removed by static interning.
+ // The allocation might be already removed by global interning.
// This can only really happen in the CTFE instance, not in miri.
if self.alloc_map.contains_key(&ptr.alloc_id) {
self.deallocate(ptr, None, MemoryKind::Stack)
&mut self,
ptr: Pointer<M::PointerTag>,
old_size_and_align: Option<(Size, Align)>,
- kind: MemoryKind<M::MemoryKinds>,
+ kind: MemoryKind<M::MemoryKind>,
) -> InterpResult<'tcx> {
trace!("deallocating: {}", ptr.alloc_id);
let (alloc_kind, mut alloc) = match self.alloc_map.remove(&ptr.alloc_id) {
Some(alloc) => alloc,
None => {
- // Deallocating static memory -- always an error
+ // Deallocating global memory -- always an error
return Err(match self.tcx.alloc_map.lock().get(ptr.alloc_id) {
Some(GlobalAlloc::Function(..)) => err_ub_format!("deallocating a function"),
Some(GlobalAlloc::Static(..)) | Some(GlobalAlloc::Memory(..)) => {
/// Allocation accessors
impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
- /// Helper function to obtain the global (tcx) allocation for a static.
+ /// Helper function to obtain a global (tcx) allocation.
/// This attempts to return a reference to an existing allocation if
/// one can be found in `tcx`. That, however, is only possible if `tcx` and
/// this machine use the same pointer tag, so it is indirected through
/// `M::tag_allocation`.
- ///
- /// Notice that every static has two `AllocId` that will resolve to the same
- /// thing here: one maps to `GlobalAlloc::Static`, this is the "lazy" ID,
- /// and the other one is maps to `GlobalAlloc::Memory`, this is returned by
- /// `const_eval_raw` and it is the "resolved" ID.
- /// The resolved ID is never used by the interpreted progrma, it is hidden.
- /// The `GlobalAlloc::Memory` branch here is still reachable though; when a static
- /// contains a reference to memory that was created during its evaluation (i.e., not to
- /// another static), those inner references only exist in "resolved" form.
- ///
- /// Assumes `id` is already canonical.
- fn get_static_alloc(
+ fn get_global_alloc(
memory_extra: &M::MemoryExtra,
tcx: TyCtxtAt<'tcx>,
id: AllocId,
+ is_write: bool,
) -> InterpResult<'tcx, Cow<'tcx, Allocation<M::PointerTag, M::AllocExtra>>> {
let alloc = tcx.alloc_map.lock().get(id);
- let alloc = match alloc {
- Some(GlobalAlloc::Memory(mem)) => Cow::Borrowed(mem),
+ let (alloc, def_id) = match alloc {
+ Some(GlobalAlloc::Memory(mem)) => (mem, None),
Some(GlobalAlloc::Function(..)) => throw_ub!(DerefFunctionPointer(id)),
None => throw_ub!(PointerUseAfterFree(id)),
Some(GlobalAlloc::Static(def_id)) => {
- // We got a "lazy" static that has not been computed yet.
+ // Notice that every static has two `AllocId` that will resolve to the same
+ // thing here: one maps to `GlobalAlloc::Static`, this is the "lazy" ID,
+ // and the other one is maps to `GlobalAlloc::Memory`, this is returned by
+ // `const_eval_raw` and it is the "resolved" ID.
+ // The resolved ID is never used by the interpreted progrma, it is hidden.
+ // The `GlobalAlloc::Memory` branch here is still reachable though; when a static
+ // contains a reference to memory that was created during its evaluation (i.e., not
+ // to another static), those inner references only exist in "resolved" form.
+ //
+ // Assumes `id` is already canonical.
if tcx.is_foreign_item(def_id) {
- trace!("get_static_alloc: foreign item {:?}", def_id);
+ trace!("get_global_alloc: foreign item {:?}", def_id);
throw_unsup!(ReadForeignStatic(def_id))
}
- trace!("get_static_alloc: Need to compute {:?}", def_id);
+ trace!("get_global_alloc: Need to compute {:?}", def_id);
let instance = Instance::mono(tcx.tcx, def_id);
let gid = GlobalId { instance, promoted: None };
- // use the raw query here to break validation cycles. Later uses of the static
- // will call the full query anyway
+ // Use the raw query here to break validation cycles. Later uses of the static
+ // will call the full query anyway.
let raw_const =
tcx.const_eval_raw(ty::ParamEnv::reveal_all().and(gid)).map_err(|err| {
// no need to report anything, the const_eval call takes care of that
let id = raw_const.alloc_id;
let allocation = tcx.alloc_map.lock().unwrap_memory(id);
- M::before_access_static(memory_extra, allocation)?;
- Cow::Borrowed(allocation)
+ (allocation, Some(def_id))
}
};
+ M::before_access_global(memory_extra, alloc, def_id, is_write)?;
+ let alloc = Cow::Borrowed(alloc);
// We got tcx memory. Let the machine initialize its "extra" stuff.
let (alloc, tag) = M::init_allocation_extra(
memory_extra,
id, // always use the ID we got as input, not the "hidden" one.
alloc,
- M::STATIC_KIND.map(MemoryKind::Machine),
+ M::GLOBAL_KIND.map(MemoryKind::Machine),
);
- debug_assert_eq!(tag, M::tag_static_base_pointer(memory_extra, id));
+ debug_assert_eq!(tag, M::tag_global_base_pointer(memory_extra, id));
Ok(alloc)
}
let id = M::canonical_alloc_id(self, id);
// The error type of the inner closure here is somewhat funny. We have two
// ways of "erroring": An actual error, or because we got a reference from
- // `get_static_alloc` that we can actually use directly without inserting anything anywhere.
+ // `get_global_alloc` that we can actually use directly without inserting anything anywhere.
// So the error type is `InterpResult<'tcx, &Allocation<M::PointerTag>>`.
let a = self.alloc_map.get_or(id, || {
- let alloc = Self::get_static_alloc(&self.extra, self.tcx, id).map_err(Err)?;
+ let alloc = Self::get_global_alloc(&self.extra, self.tcx, id, /*is_write*/ false)
+ .map_err(Err)?;
match alloc {
Cow::Borrowed(alloc) => {
// We got a ref, cheaply return that as an "error" so that the
}
Cow::Owned(alloc) => {
// Need to put it into the map and return a ref to that
- let kind = M::STATIC_KIND.expect(
- "I got an owned allocation that I have to copy but the machine does \
+ let kind = M::GLOBAL_KIND.expect(
+ "I got a global allocation that I have to copy but the machine does \
not expect that to happen",
);
Ok((MemoryKind::Machine(kind), alloc))
let tcx = self.tcx;
let memory_extra = &self.extra;
let a = self.alloc_map.get_mut_or(id, || {
- // Need to make a copy, even if `get_static_alloc` is able
+ // Need to make a copy, even if `get_global_alloc` is able
// to give us a cheap reference.
- let alloc = Self::get_static_alloc(memory_extra, tcx, id)?;
+ let alloc = Self::get_global_alloc(memory_extra, tcx, id, /*is_write*/ true)?;
if alloc.mutability == Mutability::Not {
throw_ub!(WriteToReadOnly(id))
}
- match M::STATIC_KIND {
- Some(kind) => Ok((MemoryKind::Machine(kind), alloc.into_owned())),
- None => throw_unsup!(ModifiedStatic),
- }
+ let kind = M::GLOBAL_KIND.expect(
+ "I got a global allocation that I have to copy but the machine does \
+ not expect that to happen",
+ );
+ Ok((MemoryKind::Machine(kind), alloc.into_owned()))
});
// Unpack the error type manually because type inference doesn't
// work otherwise (and we cannot help it because `impl Trait`)
// # Regular allocations
// Don't use `self.get_raw` here as that will
// a) cause cycles in case `id` refers to a static
- // b) duplicate a static's allocation in miri
+ // b) duplicate a global's allocation in miri
if let Some((_, alloc)) = self.alloc_map.get(id) {
return Ok((alloc.size, alloc.align));
}
);
}
Err(()) => {
- // static alloc?
+ // global alloc?
match self.tcx.alloc_map.lock().get(id) {
Some(GlobalAlloc::Memory(alloc)) => {
self.dump_alloc_helper(
layout: Option<TyLayout<'tcx>>,
) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> {
let tag_scalar = |scalar| match scalar {
- Scalar::Ptr(ptr) => Scalar::Ptr(self.tag_static_base_pointer(ptr)),
+ Scalar::Ptr(ptr) => Scalar::Ptr(self.tag_global_base_pointer(ptr)),
Scalar::Raw { data, size } => Scalar::Raw { data, size },
};
// Early-return cases.
let id = self.tcx.alloc_map.lock().create_memory_alloc(alloc);
// We rely on mutability being set correctly in that allocation to prevent writes
// where none should happen.
- let ptr = self.tag_static_base_pointer(Pointer::new(id, offset));
+ let ptr = self.tag_global_base_pointer(Pointer::new(id, offset));
Operand::Indirect(MemPlace::from_ptr(ptr, layout.align.abi))
}
ConstValue::Scalar(x) => Operand::Immediate(tag_scalar(x).into()),
Size::from_bytes(start as u64), // offset: `start`
);
Operand::Immediate(Immediate::new_slice(
- self.tag_static_base_pointer(ptr).into(),
+ self.tag_global_base_pointer(ptr).into(),
(end - start) as u64, // len: `end - start`
self,
))
Tag: ::std::fmt::Debug + Copy + Eq + Hash + 'static,
M: Machine<'mir, 'tcx, PointerTag = Tag>,
// FIXME: Working around https://github.com/rust-lang/rust/issues/24159
- M::MemoryMap: AllocMap<AllocId, (MemoryKind<M::MemoryKinds>, Allocation<Tag, M::AllocExtra>)>,
+ M::MemoryMap: AllocMap<AllocId, (MemoryKind<M::MemoryKind>, Allocation<Tag, M::AllocExtra>)>,
M::AllocExtra: AllocationExtra<Tag>,
{
/// Take a value, which represents a (thin or wide) reference, and make it a place.
pub fn allocate(
&mut self,
layout: TyLayout<'tcx>,
- kind: MemoryKind<M::MemoryKinds>,
+ kind: MemoryKind<M::MemoryKind>,
) -> MPlaceTy<'tcx, M::PointerTag> {
let ptr = self.memory.allocate(layout.size, layout.align.abi, kind);
MPlaceTy::from_aligned_ptr(ptr, layout)
pub fn allocate_str(
&mut self,
str: &str,
- kind: MemoryKind<M::MemoryKinds>,
+ kind: MemoryKind<M::MemoryKind>,
) -> MPlaceTy<'tcx, M::PointerTag> {
- let ptr = self.memory.allocate_static_bytes(str.as_bytes(), kind);
+ let ptr = self.memory.allocate_bytes(str.as_bytes(), kind);
let meta = Scalar::from_uint(str.len() as u128, self.pointer_size());
let mplace = MemPlace {
ptr: ptr.into(),
) -> InterpResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
// This must be an allocation in `tcx`
assert!(self.tcx.alloc_map.lock().get(raw.alloc_id).is_some());
- let ptr = self.tag_static_base_pointer(Pointer::from(raw.alloc_id));
+ let ptr = self.tag_global_base_pointer(Pointer::from(raw.alloc_id));
let layout = self.layout_of(raw.ty)?;
Ok(MPlaceTy::from_aligned_ptr(ptr, layout))
}
use rustc_hir::HirId;
use rustc_index::vec::IndexVec;
use rustc_session::lint;
-use rustc_span::Span;
+use rustc_span::{def_id::DefId, Span};
use rustc_trait_selection::traits;
use crate::const_eval::error_to_const_error;
struct ConstPropMachine;
impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine {
- type MemoryKinds = !;
+ type MemoryKind = !;
type PointerTag = ();
type ExtraFnVal = !;
type MemoryMap = FxHashMap<AllocId, (MemoryKind<!>, Allocation)>;
- const STATIC_KIND: Option<!> = None;
+ const GLOBAL_KIND: Option<!> = None;
const CHECK_ALIGN: bool = false;
}
#[inline(always)]
- fn tag_static_base_pointer(_memory_extra: &(), _id: AllocId) -> Self::PointerTag {}
+ fn tag_global_base_pointer(_memory_extra: &(), _id: AllocId) -> Self::PointerTag {}
fn box_alloc(
_ecx: &mut InterpCx<'mir, 'tcx, Self>,
l.access()
}
- fn before_access_static(
+ fn before_access_global(
_memory_extra: &(),
allocation: &Allocation<Self::PointerTag, Self::AllocExtra>,
+ _def_id: Option<DefId>,
+ is_write: bool,
) -> InterpResult<'tcx> {
- // 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 is_write {
+ throw_machine_stop_str!("can't write to global");
+ }
+ // 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_str!("can't eval mutable statics in ConstProp")
+ throw_machine_stop_str!("can't eval mutable statics in ConstProp");
}
Ok(())