From 582fbb1d62420d8d85f364d06669038f12b7e423 Mon Sep 17 00:00:00 2001 From: The8472 Date: Thu, 21 Nov 2019 13:24:48 +0100 Subject: [PATCH] use From specializations on extend if extended Vec is empty this enables in-place iteration and allocation reuse in additional cases --- library/alloc/src/vec.rs | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs index ce7ea2058b5..ffd6f5b31d4 100644 --- a/library/alloc/src/vec.rs +++ b/library/alloc/src/vec.rs @@ -2080,7 +2080,16 @@ fn into_iter(self) -> slice::IterMut<'a, T> { impl Extend for Vec { #[inline] fn extend>(&mut self, iter: I) { - >::spec_extend(self, iter.into_iter()) + if self.capacity() > 0 { + >::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 SpecFrom for Vec vector } }; + // must delegate to spec_extend() since extend() itself delegates + // to spec_from for empty Vecs as SpecExtend>::spec_extend(&mut vector, iterator); vector } @@ -2230,7 +2241,9 @@ fn from_iter(iterator: IntoIter) -> 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(&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 { fn extend>(&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]