about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDan Schatzberg <schatzberg.dan@gmail.com>2014-09-04 15:25:23 -0400
committerDan Schatzberg <schatzberg.dan@gmail.com>2014-10-02 11:22:05 -0400
commit4184396f28d5612520f7b30718df9fff6918d239 (patch)
treed3cf8319d19246c4a59be7c9ce558f6c67f15a20
parentb419e9e7396852d698602c10216051fa9f3ec2b8 (diff)
downloadrust-4184396f28d5612520f7b30718df9fff6918d239.tar.gz
rust-4184396f28d5612520f7b30718df9fff6918d239.zip
Add lifetime bounds on Items and MutItems.
This also requires a fix for Vec's MoveItems. This resolves issue #16941
-rw-r--r--src/libcollections/vec.rs56
-rw-r--r--src/libcore/slice.rs4
2 files changed, 44 insertions, 16 deletions
diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs
index 9dc122cfc7d..6fdf2fce0a2 100644
--- a/src/libcollections/vec.rs
+++ b/src/libcollections/vec.rs
@@ -845,11 +845,12 @@ 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 = (self.ptr as uint + self.len()) as *const T;
             mem::forget(self);
-            MoveItems { allocation: ptr, cap: cap, iter: iter }
+            MoveItems { allocation: ptr, cap: cap, ptr: begin, end: end }
         }
     }
 
@@ -1773,7 +1774,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> {
@@ -1793,17 +1795,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))
     }
 }
 
@@ -1811,11 +1829,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)))
+                }
+            }
         }
     }
 }
diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs
index a8becb315b2..6a8bea001bf 100644
--- a/src/libcore/slice.rs
+++ b/src/libcore/slice.rs
@@ -1163,7 +1163,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>
@@ -1206,7 +1206,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>,