libcore: Fix Items iterator for zero sized types.
This commit is contained in:
parent
f48cc74001
commit
e9e5ea2f90
2 changed files with 29 additions and 19 deletions
|
@ -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 }
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue