diff options
| -rw-r--r-- | src/libcollections/vec.rs | 31 | ||||
| -rw-r--r-- | src/librustc/middle/trans/tvec.rs | 5 |
2 files changed, 17 insertions, 19 deletions
diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index d53ecabd5a9..a284ef40257 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -27,6 +27,10 @@ use {Collection, Mutable}; use slice::{MutableOrdVector, MutableVectorAllocating, CloneableVector}; use slice::{Items, MutItems}; + +#[doc(hidden)] +pub static PTR_MARKER: u8 = 0; + /// An owned, growable vector. /// /// # Examples @@ -71,7 +75,13 @@ impl<T> Vec<T> { /// ``` #[inline] pub fn new() -> Vec<T> { - Vec { len: 0, cap: 0, ptr: 0 as *mut T } + // If we have a 0-sized vector, then the base pointer should not be NULL + // because an iterator over the slice will attempt to yield the base + // pointer as the first element in the vector, but this will end up + // being Some(NULL) which is optimized to None. So instead we set ptr + // to some arbitrary non-null value which is fine since we never call + // deallocate on the ptr if cap is 0. + Vec { len: 0, cap: 0, ptr: &PTR_MARKER as *const _ as *mut T } } /// Constructs a new, empty `Vec` with the specified capacity. @@ -88,7 +98,7 @@ impl<T> Vec<T> { #[inline] pub fn with_capacity(capacity: uint) -> Vec<T> { if mem::size_of::<T>() == 0 { - Vec { len: 0, cap: uint::MAX, ptr: 0 as *mut T } + Vec { len: 0, cap: uint::MAX, ptr: &PTR_MARKER as *const _ as *mut T } } else if capacity == 0 { Vec::new() } else { @@ -1206,15 +1216,7 @@ impl<T> Vec<T> { /// would also make any pointers to it invalid. #[inline] pub fn as_ptr(&self) -> *const T { - // If we have a 0-sized vector, then the base pointer should not be NULL - // because an iterator over the slice will attempt to yield the base - // pointer as the first element in the vector, but this will end up - // being Some(NULL) which is optimized to None. - if mem::size_of::<T>() == 0 { - 1 as *const T - } else { - self.ptr as *const T - } + self.ptr as *const T } /// Returns a mutable unsafe pointer to the vector's buffer. @@ -1226,12 +1228,7 @@ impl<T> Vec<T> { /// would also make any pointers to it invalid. #[inline] pub fn as_mut_ptr(&mut self) -> *mut T { - // see above for the 0-size check - if mem::size_of::<T>() == 0 { - 1 as *mut T - } else { - self.ptr - } + self.ptr } /// Retains only the elements specified by the predicate. diff --git a/src/librustc/middle/trans/tvec.rs b/src/librustc/middle/trans/tvec.rs index 65bf0b85008..19d7d6c6a00 100644 --- a/src/librustc/middle/trans/tvec.rs +++ b/src/librustc/middle/trans/tvec.rs @@ -155,8 +155,9 @@ pub fn trans_slice_vstore<'a>( let llcount = C_uint(ccx, count); let llfixed; if count == 0 { - // Zero-length array: just use NULL as the data pointer - llfixed = C_null(vt.llunit_ty.ptr_to()); + // Just create a zero-sized alloca to preserve + // the non-null invariant of the inner slice ptr + llfixed = base::arrayalloca(bcx, vt.llunit_ty, llcount); } else { // Make a fixed-length backing array and allocate it on the stack. llfixed = base::arrayalloca(bcx, vt.llunit_ty, llcount); |
