From c5af97546a805d0d389171fd4ed7c741b6ad14e9 Mon Sep 17 00:00:00 2001 From: The8472 Date: Sat, 3 Oct 2020 03:44:40 +0200 Subject: [PATCH] reuse RHS allocation in vec.extend() when the LHS is empty --- library/alloc/src/vec.rs | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs index b20ccd388d1f1..9eb436a2bcd46 100644 --- a/library/alloc/src/vec.rs +++ b/library/alloc/src/vec.rs @@ -2199,19 +2199,11 @@ impl SpecFromIter> for Vec { // But it is a conservative choice. let has_advanced = iterator.buf.as_ptr() as *const _ != iterator.ptr; if !has_advanced || iterator.len() >= iterator.cap / 2 { - unsafe { - let it = ManuallyDrop::new(iterator); - if has_advanced { - ptr::copy(it.ptr, it.buf.as_ptr(), it.len()); - } - return Vec::from_raw_parts(it.buf.as_ptr(), it.len(), it.cap); - } + return iterator.into_vec(); } let mut vec = Vec::new(); - // must delegate to spec_extend() since extend() itself delegates - // to spec_from for empty Vecs - vec.spec_extend(iterator); + iterator.move_to(&mut vec); vec } } @@ -2391,11 +2383,12 @@ where } impl SpecExtend> for Vec { - fn spec_extend(&mut self, mut iterator: IntoIter) { - unsafe { - self.append_elements(iterator.as_slice() as _); + fn spec_extend(&mut self, iterator: IntoIter) { + if mem::size_of::() > 0 && self.len == 0 && self.capacity() < iterator.len() { + *self = iterator.into_vec(); + return; } - iterator.ptr = iterator.end; + iterator.move_to(self); } } @@ -2928,6 +2921,23 @@ impl IntoIter { self.ptr = self.buf.as_ptr(); self.end = self.buf.as_ptr(); } + + /// Shifts the remaining elements to the front and then converts the whole allocation to a Vec + fn into_vec(self) -> Vec { + if self.ptr != self.buf.as_ptr() as *const _ { + unsafe { ptr::copy(self.ptr, self.buf.as_ptr(), self.len()) } + } + + let iter = ManuallyDrop::new(self); + unsafe { Vec::from_raw_parts(iter.buf.as_ptr(), iter.len(), iter.cap) } + } + + fn move_to(mut self, dest: &mut Vec) { + unsafe { + dest.append_elements(self.as_slice() as _); + } + self.ptr = self.end; + } } #[stable(feature = "vec_intoiter_as_ref", since = "1.46.0")]