rollup merge of #16993 : dschatzberg/items-bounds

This commit is contained in:
Alex Crichton
2014-10-02 14:49:42 -07:00
3 changed files with 81 additions and 19 deletions
+2 -2
View File
@@ -46,12 +46,12 @@ struct AbsEntries<T> {
}
/// An iterator over a BTreeMap's entries.
pub struct Entries<'a, K, V> {
pub struct Entries<'a, K: 'a, V: 'a> {
inner: AbsEntries<Traversal<'a, K, V>>
}
/// A mutable iterator over a BTreeMap's entries.
pub struct MutEntries<'a, K, V> {
pub struct MutEntries<'a, K: 'a, V: 'a> {
inner: AbsEntries<MutTraversal<'a, K, V>>
}
+77 -15
View File
@@ -791,11 +791,16 @@ pub fn move_iter(self) -> MoveItems<T> {
#[inline]
pub fn into_iter(self) -> MoveItems<T> {
unsafe {
let iter = mem::transmute(self.as_slice().iter());
let ptr = self.ptr;
let cap = self.cap;
let begin = self.ptr as *const T;
let end = if mem::size_of::<T>() == 0 {
(ptr as uint + self.len()) as *const T
} else {
ptr.offset(self.len() as int) as *const T
};
mem::forget(self);
MoveItems { allocation: ptr, cap: cap, iter: iter }
MoveItems { allocation: ptr, cap: cap, ptr: begin, end: end }
}
}
@@ -1719,7 +1724,8 @@ fn pop(&mut self) -> Option<T> {
pub struct MoveItems<T> {
allocation: *mut T, // the block of memory allocated for the vector
cap: uint, // the capacity of the vector
iter: Items<'static, T>
ptr: *const T,
end: *const T
}
impl<T> MoveItems<T> {
@@ -1728,7 +1734,7 @@ impl<T> MoveItems<T> {
pub fn unwrap(mut self) -> Vec<T> {
unsafe {
for _x in self { }
let MoveItems { allocation, cap, iter: _iter } = self;
let MoveItems { allocation, cap, ptr: _ptr, end: _end } = self;
mem::forget(self);
Vec { ptr: allocation, cap: cap, len: 0 }
}
@@ -1739,17 +1745,33 @@ impl<T> Iterator<T> for MoveItems<T> {
#[inline]
fn next<'a>(&'a mut self) -> Option<T> {
unsafe {
// Unsafely transmute from Items<'static, T> to Items<'a,
// T> because otherwise the type checker requires that T
// be bounded by 'static.
let iter: &mut Items<'a, T> = mem::transmute(&mut self.iter);
iter.next().map(|x| ptr::read(x))
if self.ptr == self.end {
None
} else {
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.
self.ptr = mem::transmute(self.ptr as uint + 1);
// Use a non-null pointer value
Some(ptr::read(mem::transmute(1u)))
} else {
let old = self.ptr;
self.ptr = self.ptr.offset(1);
Some(ptr::read(old))
}
}
}
}
#[inline]
fn size_hint(&self) -> (uint, Option<uint>) {
self.iter.size_hint()
let diff = (self.end as uint) - (self.ptr as uint);
let size = mem::size_of::<T>();
let exact = diff / (if size == 0 {1} else {size});
(exact, Some(exact))
}
}
@@ -1757,11 +1779,21 @@ impl<T> DoubleEndedIterator<T> for MoveItems<T> {
#[inline]
fn next_back<'a>(&'a mut self) -> Option<T> {
unsafe {
// Unsafely transmute from Items<'static, T> to Items<'a,
// T> because otherwise the type checker requires that T
// be bounded by 'static.
let iter: &mut Items<'a, T> = mem::transmute(&mut self.iter);
iter.next_back().map(|x| ptr::read(x))
if self.end == self.ptr {
None
} else {
if mem::size_of::<T>() == 0 {
// See above for why 'ptr.offset' isn't used
self.end = mem::transmute(self.end as uint - 1);
// Use a non-null pointer value
Some(ptr::read(mem::transmute(1u)))
} else {
self.end = self.end.offset(-1);
Some(ptr::read(mem::transmute(self.end)))
}
}
}
}
}
@@ -2473,6 +2505,36 @@ fn test_map_in_place_zero_sized() {
assert_eq!(v.map_in_place(|_| ZeroSized).as_slice(), [ZeroSized, ZeroSized].as_slice());
}
#[test]
fn test_move_items() {
let mut vec = vec!(1i, 2, 3);
let mut vec2 : Vec<int> = vec!();
for i in vec.into_iter() {
vec2.push(i);
}
assert!(vec2 == vec!(1i, 2, 3));
}
#[test]
fn test_move_items_reverse() {
let mut vec = vec!(1i, 2, 3);
let mut vec2 : Vec<int> = vec!();
for i in vec.into_iter().rev() {
vec2.push(i);
}
assert!(vec2 == vec!(3i, 2, 1));
}
#[test]
fn test_move_items_zero_sized() {
let mut vec = vec!((), (), ());
let mut vec2 : Vec<()> = vec!();
for i in vec.into_iter() {
vec2.push(i);
}
assert!(vec2 == vec!((), (), ()));
}
#[bench]
fn bench_new(b: &mut Bencher) {
b.iter(|| {
+2 -2
View File
@@ -1218,7 +1218,7 @@ fn next_back(&mut self) -> Option<$elem> {
/// Immutable slice iterator
#[experimental = "needs review"]
pub struct Items<'a, T> {
pub struct Items<'a, T: 'a> {
ptr: *const T,
end: *const T,
marker: marker::ContravariantLifetime<'a>
@@ -1261,7 +1261,7 @@ fn idx(&mut self, index: uint) -> Option<&'a T> {
/// Mutable slice iterator.
#[experimental = "needs review"]
pub struct MutItems<'a, T> {
pub struct MutItems<'a, T: 'a> {
ptr: *mut T,
end: *mut T,
marker: marker::ContravariantLifetime<'a>,