]> git.lizzy.rs Git - rust.git/commitdiff
Make vec::Drain and binary_heap::Drain covariant
authorThomas Garcia <thomasjgarcia1@gmail.com>
Thu, 21 Jul 2016 08:03:40 +0000 (01:03 -0700)
committerThomas Garcia <thomasjgarcia1@gmail.com>
Thu, 21 Jul 2016 08:03:40 +0000 (01:03 -0700)
src/libcollections/binary_heap.rs
src/libcollections/vec.rs
src/libcollectionstest/binary_heap.rs
src/libcollectionstest/vec.rs

index b9f5c6fcab9092a3d4565c5980a82f65888ff664..f6ca90234c5b4f2f0318230aa26d26bb1fe302a9 100644 (file)
@@ -1016,12 +1016,12 @@ impl<T> ExactSizeIterator for IntoIter<T> {}
 
 /// An iterator that drains a `BinaryHeap`.
 #[stable(feature = "drain", since = "1.6.0")]
-pub struct Drain<'a, T: 'a> {
-    iter: vec::Drain<'a, T>,
+pub struct Drain<T> {
+    iter: vec::Drain<T>,
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T: 'a> Iterator for Drain<'a, T> {
+impl<T> Iterator for Drain<T> {
     type Item = T;
 
     #[inline]
@@ -1036,7 +1036,7 @@ fn size_hint(&self) -> (usize, Option<usize>) {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T: 'a> DoubleEndedIterator for Drain<'a, T> {
+impl<T> DoubleEndedIterator for Drain<T> {
     #[inline]
     fn next_back(&mut self) -> Option<T> {
         self.iter.next_back()
@@ -1044,7 +1044,7 @@ fn next_back(&mut self) -> Option<T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T: 'a> ExactSizeIterator for Drain<'a, T> {}
+impl<T> ExactSizeIterator for Drain<T> {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Ord> From<Vec<T>> for BinaryHeap<T> {
index 518b94b5031b436f8f2372d86a2006fb83cc1af0..f4855cce3b4a2280891d18805c32268c3c4b7b88 100644 (file)
@@ -74,6 +74,7 @@
 use core::ops;
 use core::ptr;
 use core::slice;
+use super::vec_deque::VecDeque;
 
 use super::SpecExtend;
 use super::range::RangeArgument;
@@ -843,20 +844,20 @@ pub fn drain<R>(&mut self, range: R) -> Drain<T>
         let end = *range.end().unwrap_or(&len);
         assert!(start <= end);
         assert!(end <= len);
+        let mut drain_vec = VecDeque::new();
 
         unsafe {
-            // set self.vec length's to start, to be safe in case Drain is leaked
-            self.set_len(start);
-            // Use the borrow in the IterMut to indicate borrowing behavior of the
-            // whole Drain iterator (like &mut T).
-            let range_slice = slice::from_raw_parts_mut(self.as_mut_ptr().offset(start as isize),
-                                                        end - start);
-            Drain {
-                tail_start: end,
-                tail_len: len - end,
-                iter: range_slice.iter_mut(),
-                vec: self as *mut _,
+            for i in start..end {
+                    let p = self.as_ptr().offset(i as isize);
+                    drain_vec.push_back(ptr::read(p));
             }
+            let src = self.as_ptr().offset(end as isize);
+            let dst = self.as_mut_ptr().offset(start as isize);
+            ptr::copy(src, dst, len - end);
+            self.set_len(len - (end - start));
+        }
+        Drain {
+            deque: drain_vec
         }
     }
 
@@ -1755,64 +1756,43 @@ fn drop(&mut self) {
 /// [`drain`]: struct.Vec.html#method.drain
 /// [`Vec`]: struct.Vec.html
 #[stable(feature = "drain", since = "1.6.0")]
-pub struct Drain<'a, T: 'a> {
-    /// Index of tail to preserve
-    tail_start: usize,
-    /// Length of tail
-    tail_len: usize,
+pub struct Drain<T> {
     /// Current remaining range to remove
-    iter: slice::IterMut<'a, T>,
-    vec: *mut Vec<T>,
+    deque: VecDeque<T>
 }
 
 #[stable(feature = "drain", since = "1.6.0")]
-unsafe impl<'a, T: Sync> Sync for Drain<'a, T> {}
+unsafe impl<T: Sync> Sync for Drain<T> {}
 #[stable(feature = "drain", since = "1.6.0")]
-unsafe impl<'a, T: Send> Send for Drain<'a, T> {}
+unsafe impl<T: Send> Send for Drain<T> {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> Iterator for Drain<'a, T> {
+impl<T> Iterator for Drain<T> {
     type Item = T;
 
     #[inline]
     fn next(&mut self) -> Option<T> {
-        self.iter.next().map(|elt| unsafe { ptr::read(elt as *const _) })
+        self.deque.pop_front()
     }
 
     fn size_hint(&self) -> (usize, Option<usize>) {
-        self.iter.size_hint()
+        (self.deque.len(), Some(self.deque.len()))
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> DoubleEndedIterator for Drain<'a, T> {
+impl<T> DoubleEndedIterator for Drain<T> {
     #[inline]
     fn next_back(&mut self) -> Option<T> {
-        self.iter.next_back().map(|elt| unsafe { ptr::read(elt as *const _) })
+        self.deque.pop_back()
     }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> Drop for Drain<'a, T> {
+impl<T> Drop for Drain<T> {
     fn drop(&mut self) {
-        // exhaust self first
-        while let Some(_) = self.next() {}
-
-        if self.tail_len > 0 {
-            unsafe {
-                let source_vec = &mut *self.vec;
-                // memmove back untouched tail, update to new length
-                let start = source_vec.len();
-                let tail = self.tail_start;
-                let src = source_vec.as_ptr().offset(tail as isize);
-                let dst = source_vec.as_mut_ptr().offset(start as isize);
-                ptr::copy(src, dst, self.tail_len);
-                source_vec.set_len(start + self.tail_len);
-            }
-        }
     }
 }
 
-
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> ExactSizeIterator for Drain<'a, T> {}
+impl<T> ExactSizeIterator for Drain<T> {}
index be933abe41fe201f8d1c8be9efd9e88d1b708de0..39efc9fc22c39efb97d78bcc8cb100743978fb99 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use std::collections::BinaryHeap;
+use std::collections::binary_heap::Drain;
 
 #[test]
 fn test_iterator() {
@@ -292,3 +293,8 @@ fn test_extend_specialization() {
 
     assert_eq!(a.into_sorted_vec(), [-20, -10, 1, 2, 3, 3, 5, 43]);
 }
+
+#[allow(dead_code)]
+fn assert_covariance() {
+    fn drain<'new>(d: Drain<&'static str>) -> Drain<&'new str> { d }
+}
index cb99659cc0ead7238fd30d75d49cdef095aea976..01656b44a8495a5e88a9bd320f74a18cda49411e 100644 (file)
@@ -11,6 +11,7 @@
 use std::borrow::Cow;
 use std::iter::{FromIterator, repeat};
 use std::mem::size_of;
+use std::vec::Drain;
 
 use test::Bencher;
 
@@ -510,6 +511,11 @@ fn test_cow_from() {
     }
 }
 
+#[allow(dead_code)]
+fn assert_covariance() {
+    fn drain<'new>(d: Drain<&'static str>) -> Drain<&'new str> { d }
+}
+
 #[bench]
 fn bench_new(b: &mut Bencher) {
     b.iter(|| {