From f85a5337ab0f8b492cb8df56a7c2af103010037e Mon Sep 17 00:00:00 2001 From: Sean McArthur Date: Wed, 19 Apr 2017 11:57:29 -0700 Subject: [PATCH] specialize Extend for Vec with IntoIter --- src/libcollections/tests/vec.rs | 22 ++++++++++++++++++++++ src/libcollections/vec.rs | 27 +++++++++++++++++++-------- 2 files changed, 41 insertions(+), 8 deletions(-) diff --git a/src/libcollections/tests/vec.rs b/src/libcollections/tests/vec.rs index 63df0eb730509..64c76142b59d6 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 35ecf411db4e0..bf54359226212 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1039,18 +1039,22 @@ impl Vec { #[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. /// @@ -1681,7 +1685,7 @@ impl SpecExtend for Vec 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 { @@ -1726,6 +1730,13 @@ impl SpecExtend> for Vec { vector } } + + fn spec_extend(&mut self, mut iterator: IntoIter) { + unsafe { + self.append_elements(iterator.as_slice() as _); + } + iterator.ptr = iterator.end; + } } impl<'a, T: 'a, I> SpecExtend<&'a T, I> for Vec