From bc697eef1edfdd424374ed2d81bcadddbeed2f01 Mon Sep 17 00:00:00 2001 From: Tage Johansson Date: Mon, 15 Dec 2025 16:31:54 +0100 Subject: [PATCH 1/4] Add `ArrayVec::new_in_place()` --- src/arrayvec.rs | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/arrayvec.rs b/src/arrayvec.rs index e5ea52dc..b07bdece 100644 --- a/src/arrayvec.rs +++ b/src/arrayvec.rs @@ -87,6 +87,46 @@ impl ArrayVec { } } + /// Initialize an empty `ArrayVec` in-place. + /// + /// Useful when you want to store a huge `ArrayVec` in some pre-initialized memory and + /// don't want to create and move it from the stack. + /// This is very cheap as all elements are uninitialized when the vec is empty. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// use std::mem::MaybeUninit; + /// + /// let mut place = MaybeUninit::>::uninit(); + /// let vec = ArrayVec::new_in_place(&mut place); + /// assert_eq!(vec.len(), 0); + /// assert_eq!(vec.capacity(), 10); + /// vec.push(42); + /// assert_eq!(vec, [42].as_slice()); + /// ``` + /// + /// ### Creating an `ArrayVec` on the Heap + /// + /// The return value is the same reference as passed to the function. Thus you can just + /// ignore that and assume that your [`MaybeUninit`] is initialized. + /// + /// ``` + /// use arrayvec::ArrayVec; + /// use std::mem::MaybeUninit; + /// + /// let mut place = Box::new_uninit(); + /// ArrayVec::new_in_place(&mut place); + /// let vec: Box> = unsafe { place.assume_init() }; + /// assert_eq!(vec.len(), 0); + /// assert_eq!(vec.capacity(), 10); + /// ``` + #[inline] + pub fn new_in_place(uninit: &mut MaybeUninit) -> &mut Self { + let ptr = uninit.as_mut_ptr(); + unsafe { ptr::addr_of_mut!((*ptr).len).write(0); } + unsafe { uninit.assume_init_mut() } + } + /// Create a new empty `ArrayVec` (const fn). /// /// The maximum capacity is given by the generic parameter `CAP`. From 753387dbe2514b68723ae3bc41b6a25fb4954528 Mon Sep 17 00:00:00 2001 From: Tage Johansson Date: Mon, 15 Dec 2025 16:53:13 +0100 Subject: [PATCH 2/4] update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 056e6c0f..f74f6e5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ Recent Changes (arrayvec) ========================= +- Enable in-place initialization [#304](https://github.com/bluss/arrayvec/pull/304) + ## 0.7.6 - Fix no-std build [#274](https://github.com/bluss/arrayvec/pull/274) From 77b22704c3010e14d77e1c9e6d55eeacf5d38491 Mon Sep 17 00:00:00 2001 From: Tage Johansson Date: Tue, 16 Dec 2025 09:43:04 +0100 Subject: [PATCH 3/4] ci: Skip running doctest for `ArrayVec::new_in_place` on Rust older than 1.82 --- .github/workflows/ci.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a390ff55..c38bbcb4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,10 +21,13 @@ jobs: features: serde experimental: false # doctest of `ArrayVec::spare_capacity_mut` has MSRV 1.55 - test-args: --skip spare_capacity_mut + # doctest of `ArrayVec::new_in_place` has MSRV 1.82 + test-args: --skip spare_capacity_mut --skip new_in_place - rust: 1.70.0 features: serde experimental: false + # doctest of `ArrayVec::new_in_place` has MSRV 1.82 + test-args: --skip new_in_place - rust: stable features: bench: true From 92a8816cd44d85b5059e2f62a28fdcc6eee61e60 Mon Sep 17 00:00:00 2001 From: Tage Johansson Date: Tue, 16 Dec 2025 09:58:20 +0100 Subject: [PATCH 4/4] Make `ArrayVec::new_in_place` compatable with Rust 1.51 --- src/arrayvec.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/arrayvec.rs b/src/arrayvec.rs index b07bdece..52c9b04c 100644 --- a/src/arrayvec.rs +++ b/src/arrayvec.rs @@ -124,7 +124,8 @@ impl ArrayVec { pub fn new_in_place(uninit: &mut MaybeUninit) -> &mut Self { let ptr = uninit.as_mut_ptr(); unsafe { ptr::addr_of_mut!((*ptr).len).write(0); } - unsafe { uninit.assume_init_mut() } + // XXX: Once MSRV >= 1.55 we can use: unsafe { uninit.assume_init_mut() } + unsafe { &mut *ptr } } /// Create a new empty `ArrayVec` (const fn).