Skip to content

Commit

Permalink
Auto merge of #41191 - seanmonstar:spec-extend-vec-intoiter, r=alexcr…
Browse files Browse the repository at this point in the history
…ichton

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.
  • Loading branch information
bors committed Apr 20, 2017
2 parents fa6b50f + f85a533 commit 968ae7b
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 8 deletions.
22 changes: 22 additions & 0 deletions src/libcollections/tests/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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]
Expand Down
27 changes: 19 additions & 8 deletions src/libcollections/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
///
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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>
Expand Down

0 comments on commit 968ae7b

Please sign in to comment.