use From specializations on extend if extended Vec is empty

this enables in-place iteration and allocation reuse in additional cases
This commit is contained in:
The8472 2019-11-21 13:24:48 +01:00
parent a596ff36b5
commit 582fbb1d62

View File

@ -2080,7 +2080,16 @@ fn into_iter(self) -> slice::IterMut<'a, T> {
impl<T> Extend<T> for Vec<T> {
#[inline]
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
<Self as SpecExtend<T, I::IntoIter>>::spec_extend(self, iter.into_iter())
if self.capacity() > 0 {
<Self as SpecExtend<T, I::IntoIter>>::spec_extend(self, iter.into_iter())
} else {
// if self has no allocation then use the more powerful from_iter specializations
let other = SpecFrom::from_iter(iter.into_iter());
// replace self, don't run drop since self was empty
unsafe {
ptr::write(self, other);
}
}
}
#[inline]
@ -2121,6 +2130,8 @@ impl<T, I> SpecFrom<T, I> for Vec<T>
vector
}
};
// must delegate to spec_extend() since extend() itself delegates
// to spec_from for empty Vecs
<Vec<T> as SpecExtend<T, I>>::spec_extend(&mut vector, iterator);
vector
}
@ -2230,7 +2241,9 @@ fn from_iter(iterator: IntoIter<T>) -> Self {
}
let mut vec = Vec::new();
vec.extend(iterator);
// must delegate to spec_extend() since extend() itself delegates
// to spec_from for empty Vecs
vec.spec_extend(iterator);
vec
}
}
@ -2475,7 +2488,16 @@ pub fn drain_filter<F>(&mut self, filter: F) -> DrainFilter<'_, T, F>
#[stable(feature = "extend_ref", since = "1.2.0")]
impl<'a, T: 'a + Copy> Extend<&'a T> for Vec<T> {
fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
self.spec_extend(iter.into_iter())
if self.capacity() > 0 {
self.spec_extend(iter.into_iter())
} else {
// if self has no allocation then use the more powerful from_iter specializations
let other = SpecFrom::from_iter(iter.into_iter());
// replace self, don't run drop since self was empty
unsafe {
ptr::write(self, other);
}
}
}
#[inline]