diff --git a/src/eval_context.rs b/src/eval_context.rs index 76ed797684b8..07f63fad6cf4 100644 --- a/src/eval_context.rs +++ b/src/eval_context.rs @@ -414,7 +414,7 @@ pub fn deallocate_local(&mut self, local: Option) -> EvalResult<'tcx> { let ptr = ptr.to_ptr()?; self.memory.dump_alloc(ptr.alloc_id); match self.memory.get(ptr.alloc_id)?.kind { - ::memory::Kind::Static => {}, + ::memory::Kind::Static | ::memory::Kind::UninitializedStatic => {}, ::memory::Kind::Stack => self.memory.deallocate(ptr, None, ::memory::Kind::Stack)?, other => bug!("local contained non-stack memory: {:?}", other), } diff --git a/src/memory.rs b/src/memory.rs index 75ebff2f97b0..6b181e31063a 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -193,9 +193,9 @@ pub fn allocate_cached(&mut self, bytes: &[u8]) -> EvalResult<'tcx, MemoryPointe return Ok(MemoryPointer::new(alloc_id, 0)); } - let ptr = self.allocate(bytes.len() as u64, 1, Kind::Static)?; + let ptr = self.allocate(bytes.len() as u64, 1, Kind::UninitializedStatic)?; self.write_bytes(PrimVal::Ptr(ptr), bytes)?; - self.mark_static_initalized(ptr.alloc_id, Mutability::Mutable)?; + self.mark_static_initalized(ptr.alloc_id, Mutability::Immutable)?; self.literal_alloc_cache.insert(bytes.to_vec(), ptr.alloc_id); Ok(ptr) } @@ -605,7 +605,24 @@ pub fn mark_static_initalized(&mut self, alloc_id: AllocId, mutability: Mutabili // do not use `self.get_mut(alloc_id)` here, because we might have already marked a // sub-element or have circular pointers (e.g. `Rc`-cycles) let relocations = match self.alloc_map.get_mut(&alloc_id) { - Some(&mut Allocation { ref mut relocations, kind: ref mut kind @ Kind::UninitializedStatic, ref mut mutable, .. }) => { + Some(&mut Allocation { ref mut relocations, ref mut kind, ref mut mutable, .. }) => { + match *kind { + // const eval results can refer to "locals". + // E.g. `const Foo: &u32 = &1;` refers to the temp local that stores the `1` + Kind::Stack | + // The entire point of this function + Kind::UninitializedStatic | + // In the future const eval will allow heap allocations so we'll need to protect them + // from deallocation, too + Kind::Rust | + Kind::C => {}, + Kind::Static => { + trace!("mark_static_initalized: skipping already initialized static referred to by static currently being initialized"); + return Ok(()); + }, + // FIXME: This could be allowed, but not for env vars set during miri execution + Kind::Env => return Err(EvalError::Unimplemented("statics can't refer to env vars".to_owned())), + } *kind = Kind::Static; *mutable = mutability; // take out the relocations vector to free the borrow on self, so we can call diff --git a/src/traits.rs b/src/traits.rs index b3e77a9299c1..68d027bc6338 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -51,7 +51,7 @@ pub fn get_vtable(&mut self, ty: Ty<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) -> let ptr_size = self.memory.pointer_size(); let methods = ::rustc::traits::get_vtable_methods(self.tcx, trait_ref); - let vtable = self.memory.allocate(ptr_size * (3 + methods.count() as u64), ptr_size, Kind::Static)?; + let vtable = self.memory.allocate(ptr_size * (3 + methods.count() as u64), ptr_size, Kind::UninitializedStatic)?; let drop = ::eval_context::resolve_drop_in_place(self.tcx, ty); let drop = self.memory.create_fn_alloc(drop); diff --git a/tests/compile-fail/stack_free.rs b/tests/compile-fail/stack_free.rs index 1828d809b208..08ff7457b76b 100644 --- a/tests/compile-fail/stack_free.rs +++ b/tests/compile-fail/stack_free.rs @@ -1,5 +1,7 @@ +// error-pattern: tried to deallocate Stack memory but gave Rust as the kind + fn main() { let x = 42; let bad_box = unsafe { std::mem::transmute::<&i32, Box>(&x) }; - drop(bad_box); //~ ERROR tried to deallocate Stack memory but gave Rust as the kind + drop(bad_box); }