From cd6dad641ca635f0c71d7dd0a34de8211939e8d9 Mon Sep 17 00:00:00 2001 From: Waffle Date: Wed, 3 Feb 2021 01:56:51 +0300 Subject: [PATCH 1/4] Make Vec::split_at_spare_mut public This commit introduces a new method to the public API, under `vec_split_at_spare` feature gate: ```rust impl impl Vec { pub fn split_at_spare_mut(&mut self) -> (&mut [T], &mut [MaybeUninit]); } ``` The method returns 2 slices, one slice references the content of the vector, and the other references the remaining spare capacity. The method was previously implemented while adding `Vec::extend_from_within`, and used to implement `Vec::spare_capacity_mut` (as the later is just a subset of former one). --- library/alloc/src/vec/mod.rs | 39 +++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index ede1601fa33cc..91535e9b527b1 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1828,8 +1828,45 @@ impl Vec { self.split_at_spare_mut().1 } + /// Returns vector content as a slice of `T`, among with the remaining spare + /// capacity of the vector as a slice of `MaybeUninit`. + /// + /// The returned spare capacity slice can be used to fill the vector with data + /// (e.g. by reading from a file) before marking the data as initialized using + /// the [`set_len`] method. + /// + /// [`set_len`]: Vec::set_len + /// + /// # Examples + /// + /// ``` + /// #![feature(vec_split_at_spare, maybe_uninit_extra)] + /// + /// let mut v = vec![1, 1, 2]; + /// + /// // Reserve additional space big enough for 10 elements. + /// v.reserve(10); + /// + /// let (init, uninit) = v.split_at_spare_mut(); + /// let sum = init.iter().copied().sum::(); + /// + /// // Fill in the next 4 elements. + /// uninit[0].write(sum); + /// uninit[1].write(sum * 2); + /// uninit[2].write(sum * 3); + /// uninit[3].write(sum * 4); + /// + /// // Mark the 4 elements of the vector as being initialized. + /// unsafe { + /// let len = v.len(); + /// v.set_len(len + 4); + /// } + /// + /// assert_eq!(&v, &[1, 1, 2, 4, 8, 12, 16]); + /// ``` + #[unstable(feature = "vec_split_at_spare", issue = "none")] #[inline] - fn split_at_spare_mut(&mut self) -> (&mut [T], &mut [MaybeUninit]) { + pub fn split_at_spare_mut(&mut self) -> (&mut [T], &mut [MaybeUninit]) { let ptr = self.as_mut_ptr(); // Safety: From 476a57a628ea358d01a2830db67e24149521f144 Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Wed, 3 Feb 2021 13:53:58 +0300 Subject: [PATCH 2/4] fix typo in library/alloc/src/vec/mod.rs Co-authored-by: the8472 --- library/alloc/src/vec/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 91535e9b527b1..df449ca68032d 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1828,7 +1828,7 @@ impl Vec { self.split_at_spare_mut().1 } - /// Returns vector content as a slice of `T`, among with the remaining spare + /// Returns vector content as a slice of `T`, along with the remaining spare /// capacity of the vector as a slice of `MaybeUninit`. /// /// The returned spare capacity slice can be used to fill the vector with data From 76223fafb4f6d552ff7b310a00dd5ee23cb4a1b6 Mon Sep 17 00:00:00 2001 From: Waffle Date: Wed, 3 Feb 2021 14:14:55 +0300 Subject: [PATCH 3/4] Add note to `Vec::split_at_spare_mut` docs that the method is low-level --- library/alloc/src/vec/mod.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index df449ca68032d..8620200b038b0 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1837,6 +1837,21 @@ impl Vec { /// /// [`set_len`]: Vec::set_len /// + /// Note that this is a low-level API, which should be used with care for + /// optimization purposes. If you need to append data to a `Vec` + /// you can use [`push`], [`extend`], [`extend_from_slice`], + /// [`extend_from_within`], [`insert`], [`append`], [`resize`] or + /// [`resize_with`], depending on your exact needs. + /// + /// [`push`]: Vec::push + /// [`extend`]: Vec::extend + /// [`extend_from_slice`]: Vec::extend_from_slice + /// [`extend_from_within`]: Vec::extend_from_within + /// [`insert`]: Vec::insert + /// [`append`]: Vec::append + /// [`resize`]: Vec::resize + /// [`resize_with`]: Vec::resize_with + /// /// # Examples /// /// ``` From 8ff7b75c016af8bebf995f12e7e5b246ad849470 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Wed, 10 Feb 2021 09:50:59 +1000 Subject: [PATCH 4/4] update tracking issue for vec_split_at_spare --- library/alloc/src/vec/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 8620200b038b0..c7b4c98041b2e 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1879,7 +1879,7 @@ impl Vec { /// /// assert_eq!(&v, &[1, 1, 2, 4, 8, 12, 16]); /// ``` - #[unstable(feature = "vec_split_at_spare", issue = "none")] + #[unstable(feature = "vec_split_at_spare", issue = "81944")] #[inline] pub fn split_at_spare_mut(&mut self) -> (&mut [T], &mut [MaybeUninit]) { let ptr = self.as_mut_ptr();