diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs index a2c406be5a901..b6c255e793066 100644 --- a/src/liballoc/heap.rs +++ b/src/liballoc/heap.rs @@ -86,10 +86,11 @@ pub fn stats_print() { imp::stats_print(); } -// The compiler never calls `exchange_free` on Box, so zero-size -// allocations can point to this `static`. It would be incorrect to use a null -// pointer, due to enums assuming types like unique pointers are never null. -pub static mut EMPTY: uint = 12345; +/// An arbitrary non-null address to represent zero-size allocations. +/// +/// This preserves the non-null invariant for types like `Box`. The address may overlap with +/// non-zero-size memory allocations. +pub static EMPTY: *mut () = 0x1 as *mut (); /// The allocator for unique pointers. #[cfg(not(test))] @@ -97,7 +98,7 @@ pub static mut EMPTY: uint = 12345; #[inline] unsafe fn exchange_malloc(size: uint, align: uint) -> *mut u8 { if size == 0 { - &EMPTY as *const uint as *mut u8 + EMPTY as *mut u8 } else { allocate(size, align) } diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 6fc367474bb7b..3597ab285baf0 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -12,7 +12,7 @@ use core::prelude::*; -use alloc::heap::{allocate, reallocate, deallocate}; +use alloc::heap::{EMPTY, allocate, reallocate, deallocate}; use core::cmp::max; use core::default::Default; use core::fmt; @@ -26,10 +26,6 @@ use {Mutable, MutableSeq}; use slice::{MutableOrdSlice, MutableSliceAllocating, CloneableVector}; use slice::{Items, MutItems}; - -#[doc(hidden)] -pub static PTR_MARKER: u8 = 0; - /// An owned, growable vector. /// /// # Examples @@ -122,7 +118,7 @@ impl Vec { // non-null value which is fine since we never call deallocate on the ptr // if cap is 0. The reason for this is because the pointer of a slice // being NULL would break the null pointer optimization for enums. - Vec { len: 0, cap: 0, ptr: &PTR_MARKER as *const _ as *mut T } + Vec { len: 0, cap: 0, ptr: EMPTY as *mut T } } /// Constructs a new, empty `Vec` with the specified capacity. @@ -155,7 +151,7 @@ impl Vec { #[inline] pub fn with_capacity(capacity: uint) -> Vec { if mem::size_of::() == 0 { - Vec { len: 0, cap: uint::MAX, ptr: &PTR_MARKER as *const _ as *mut T } + Vec { len: 0, cap: uint::MAX, ptr: EMPTY as *mut T } } else if capacity == 0 { Vec::new() } else { diff --git a/src/libsyntax/owned_slice.rs b/src/libsyntax/owned_slice.rs index 7d8a9e08ba02b..33482ec0eb359 100644 --- a/src/libsyntax/owned_slice.rs +++ b/src/libsyntax/owned_slice.rs @@ -12,6 +12,7 @@ use std::fmt; use std::default::Default; use std::hash; use std::{mem, raw, ptr, slice, vec}; +use std::rt::heap::EMPTY; use serialize::{Encodable, Decodable, Encoder, Decoder}; /// A non-growable owned slice. This would preferably become `~[T]` @@ -81,10 +82,9 @@ impl OwnedSlice { } pub fn as_slice<'a>(&'a self) -> &'a [T] { - static PTR_MARKER: u8 = 0; let ptr = if self.data.is_null() { // length zero, i.e. this will never be read as a T. - &PTR_MARKER as *const u8 as *const T + EMPTY as *const T } else { self.data as *const T };