about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/libcollections/tests/vec.rs22
-rw-r--r--src/libcollections/vec.rs27
2 files changed, 41 insertions, 8 deletions
diff --git a/src/libcollections/tests/vec.rs b/src/libcollections/tests/vec.rs
index 63df0eb7305..64c76142b59 100644
--- a/src/libcollections/tests/vec.rs
+++ b/src/libcollections/tests/vec.rs
@@ -84,6 +84,9 @@ fn test_extend() {
     let mut v = Vec::new();
     let mut w = Vec::new();
 
+    v.extend(w.clone());
+    assert_eq!(v, &[]);
+
     v.extend(0..3);
     for i in 0..3 {
         w.push(i)
@@ -100,6 +103,25 @@ fn test_extend() {
 
     v.extend(w.clone()); // specializes to `append`
     assert!(v.iter().eq(w.iter().chain(w.iter())));
+
+    // Zero sized types
+    #[derive(PartialEq, Debug)]
+    struct Foo;
+
+    let mut a = Vec::new();
+    let b = vec![Foo, Foo];
+
+    a.extend(b);
+    assert_eq!(a, &[Foo, Foo]);
+
+    // Double drop
+    let mut count_x = 0;
+    {
+        let mut x = Vec::new();
+        let y = vec![DropCounter { count: &mut count_x }];
+        x.extend(y);
+    }
+    assert_eq!(count_x, 1);
 }
 
 #[test]
diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs
index a3c529f3585..6deb87ae772 100644
--- a/src/libcollections/vec.rs
+++ b/src/libcollections/vec.rs
@@ -1041,18 +1041,22 @@ impl<T> Vec<T> {
     #[inline]
     #[stable(feature = "append", since = "1.4.0")]
     pub fn append(&mut self, other: &mut Self) {
-        self.reserve(other.len());
-        let len = self.len();
-        unsafe {
-            ptr::copy_nonoverlapping(other.as_ptr(), self.get_unchecked_mut(len), other.len());
-        }
-
-        self.len += other.len();
         unsafe {
+            self.append_elements(other.as_slice() as _);
             other.set_len(0);
         }
     }
 
+    /// Appends elements to `Self` from other buffer.
+    #[inline]
+    unsafe fn append_elements(&mut self, other: *const [T]) {
+        let count = (*other).len();
+        self.reserve(count);
+        let len = self.len();
+        ptr::copy_nonoverlapping(other as *const T, self.get_unchecked_mut(len), count);
+        self.len += count;
+    }
+
     /// Create a draining iterator that removes the specified range in the vector
     /// and yields the removed items.
     ///
@@ -1738,7 +1742,7 @@ impl<T, I> SpecExtend<T, I> for Vec<T>
         vector
     }
 
-    fn spec_extend(&mut self, iterator: I) {
+    default fn spec_extend(&mut self, iterator: I) {
         // This is the case for a TrustedLen iterator.
         let (low, high) = iterator.size_hint();
         if let Some(high_value) = high {
@@ -1783,6 +1787,13 @@ impl<T> SpecExtend<T, IntoIter<T>> for Vec<T> {
             vector
         }
     }
+
+    fn spec_extend(&mut self, mut iterator: IntoIter<T>) {
+        unsafe {
+            self.append_elements(iterator.as_slice() as _);
+        }
+        iterator.ptr = iterator.end;
+    }
 }
 
 impl<'a, T: 'a, I> SpecExtend<&'a T, I> for Vec<T>