libcore: Fix Items iterator for zero sized types.

This commit is contained in:
Luqman Aden 2014-07-04 15:29:47 -07:00
parent f48cc74001
commit e9e5ea2f90
2 changed files with 29 additions and 19 deletions

View file

@ -75,12 +75,10 @@ impl<T> Vec<T> {
/// ```
#[inline]
pub fn new() -> Vec<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.
// We want ptr to never be NULL so instead we set it to some arbitrary
// 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 }
}

View file

@ -884,17 +884,20 @@ macro_rules! iterator {
if self.ptr == self.end {
None
} else {
let old = self.ptr;
self.ptr = if mem::size_of::<T>() == 0 {
if mem::size_of::<T>() == 0 {
// purposefully don't use 'ptr.offset' because for
// vectors with 0-size elements this would return the
// same pointer.
transmute(self.ptr as uint + 1)
} else {
self.ptr.offset(1)
};
self.ptr = transmute(self.ptr as uint + 1);
Some(transmute(old))
// Use a non-null pointer value
Some(transmute(1u))
} else {
let old = self.ptr;
self.ptr = self.ptr.offset(1);
Some(transmute(old))
}
}
}
}
@ -916,13 +919,17 @@ macro_rules! iterator {
if self.end == self.ptr {
None
} else {
self.end = if mem::size_of::<T>() == 0 {
if mem::size_of::<T>() == 0 {
// See above for why 'ptr.offset' isn't used
transmute(self.end as uint - 1)
self.end = transmute(self.end as uint - 1);
// Use a non-null pointer value
Some(transmute(1u))
} else {
self.end.offset(-1)
};
Some(transmute(self.end))
self.end = self.end.offset(-1);
Some(transmute(self.end))
}
}
}
}
@ -956,7 +963,12 @@ impl<'a, T> RandomAccessIterator<&'a T> for Items<'a, T> {
fn idx(&mut self, index: uint) -> Option<&'a T> {
unsafe {
if index < self.indexable() {
transmute(self.ptr.offset(index as int))
if mem::size_of::<T>() == 0 {
// Use a non-null pointer value
Some(transmute(1u))
} else {
Some(transmute(self.ptr.offset(index as int)))
}
} else {
None
}