Auto merge of #41191 - seanmonstar:spec-extend-vec-intoiter, r=alexcrichton

specialize Extend for Vec with IntoIter

Before, `vec.extend(&other_vec)` was quite a bit faster than `vec.extend(other_vec)`. This allows extending by consuming a vec to use the same code as extending from a slice.
This commit is contained in:
bors 2017-04-20 13:08:07 +00:00
commit 968ae7babe
2 changed files with 41 additions and 8 deletions

View file

@ -84,6 +84,9 @@ fn test_extend() {
let mut v = Vec::new(); let mut v = Vec::new();
let mut w = Vec::new(); let mut w = Vec::new();
v.extend(w.clone());
assert_eq!(v, &[]);
v.extend(0..3); v.extend(0..3);
for i in 0..3 { for i in 0..3 {
w.push(i) w.push(i)
@ -100,6 +103,25 @@ fn test_extend() {
v.extend(w.clone()); // specializes to `append` v.extend(w.clone()); // specializes to `append`
assert!(v.iter().eq(w.iter().chain(w.iter()))); 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] #[test]

View file

@ -1041,18 +1041,22 @@ impl<T> Vec<T> {
#[inline] #[inline]
#[stable(feature = "append", since = "1.4.0")] #[stable(feature = "append", since = "1.4.0")]
pub fn append(&mut self, other: &mut Self) { 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 { unsafe {
self.append_elements(other.as_slice() as _);
other.set_len(0); 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 /// Create a draining iterator that removes the specified range in the vector
/// and yields the removed items. /// and yields the removed items.
/// ///
@ -1738,7 +1742,7 @@ impl<T, I> SpecExtend<T, I> for Vec<T>
vector vector
} }
fn spec_extend(&mut self, iterator: I) { default fn spec_extend(&mut self, iterator: I) {
// This is the case for a TrustedLen iterator. // This is the case for a TrustedLen iterator.
let (low, high) = iterator.size_hint(); let (low, high) = iterator.size_hint();
if let Some(high_value) = high { if let Some(high_value) = high {
@ -1783,6 +1787,13 @@ impl<T> SpecExtend<T, IntoIter<T>> for Vec<T> {
vector 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> impl<'a, T: 'a, I> SpecExtend<&'a T, I> for Vec<T>