diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs index b20ccd388d1f1..85ca8ea4738e7 100644 --- a/library/alloc/src/vec.rs +++ b/library/alloc/src/vec.rs @@ -243,8 +243,8 @@ use crate::raw_vec::RawVec; /// * It would penalize the general case, incurring an additional branch /// on every access. /// -/// `Vec` will never automatically shrink itself, even if completely empty. This -/// ensures no unnecessary allocations or deallocations occur. Emptying a `Vec` +/// `Vec` will not automatically shrink itself, even if completely empty, when doing so +/// would cause unnecessary allocations or deallocations to occur. Emptying a `Vec` /// and then filling it back up to the same [`len`] should incur no calls to /// the allocator. If you wish to free up unused memory, use /// [`shrink_to_fit`]. @@ -1257,6 +1257,14 @@ impl Vec { #[inline] #[stable(feature = "append", since = "1.4.0")] pub fn append(&mut self, other: &mut Self) { + // Reuses other if doing so allows us to turn a certain reallocation within self + // into a potential, future reallocation in other. + // The capacity limit ensures that we are not stealing a large preallocation from `other` + // that is not commensurate with the avoided reallocation in self. + if self.len == 0 && self.capacity() < other.len && other.capacity() / 2 <= other.len { + mem::swap(self, other); + return; + } unsafe { self.append_elements(other.as_slice() as _); other.set_len(0);