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:
commit
968ae7babe
2 changed files with 41 additions and 8 deletions
|
|
@ -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]
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue