about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2014-10-02 14:49:42 -0700
committerAlex Crichton <alex@alexcrichton.com>2014-10-02 14:49:42 -0700
commit8bb5a674a434da86de499113d2c6bce1ffd23d8a (patch)
tree4155e4ac5a90d0495241084952ac6c558ff8c002 /src
parent4c8d0334ee480d54b6917e780cfa2da3747ecfc1 (diff)
parent49e593c3d6494e210c215b4d353270616450980f (diff)
downloadrust-8bb5a674a434da86de499113d2c6bce1ffd23d8a.tar.gz
rust-8bb5a674a434da86de499113d2c6bce1ffd23d8a.zip
rollup merge of #16993 : dschatzberg/items-bounds
Diffstat (limited to 'src')
-rw-r--r--src/libcollections/btree/map.rs4
-rw-r--r--src/libcollections/vec.rs92
-rw-r--r--src/libcore/slice.rs4
3 files changed, 81 insertions, 19 deletions
diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs
index b0ba2254621..ab160595433 100644
--- a/src/libcollections/btree/map.rs
+++ b/src/libcollections/btree/map.rs
@@ -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>>
 }
 
diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs
index 280fbdeffa2..f5d61a644a3 100644
--- a/src/libcollections/vec.rs
+++ b/src/libcollections/vec.rs
@@ -791,11 +791,16 @@ impl<T> Vec<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 @@ impl<T> MutableSeq<T> for Vec<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 @@ mod tests {
         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(|| {
diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs
index 1a00107a216..9f925f9d371 100644
--- a/src/libcore/slice.rs
+++ b/src/libcore/slice.rs
@@ -1218,7 +1218,7 @@ macro_rules! iterator {
 
 /// 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 @@ impl<'a, T> RandomAccessIterator<&'a T> for Items<'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>,