From be5620eca24f74b9e192a8990dd74c7a37ee5c3f Mon Sep 17 00:00:00 2001 From: Otger Comas Valls Date: Sun, 27 Apr 2025 19:10:47 +0200 Subject: [PATCH] reimplement from_buf --- src/lib.rs | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index f05bc3f..21bde96 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -673,11 +673,27 @@ impl SmallVec { } #[inline] - pub const fn from_buf(buf: [T; N]) -> Self { - // SAFETY: all the members in 0..N are initialized + pub const fn from_buf(elements: [T; S]) -> Self { + assert!(S <= N); // Free check since the values are known at compile time + + // Althought we create a new buffer, since S and N are known at compile time, + // even with `-C opt-level=1`, it gets optimized as best as it could be. (Checked with ) + let mut buf: MaybeUninit<[T; N]> = MaybeUninit::uninit(); + + // SAFETY: buf and elements do not overlap, are aligned and have space + // for at least S elements since S <= N. + // We will drop the elements only once since we do forget(elements). + unsafe { + copy_nonoverlapping(elements.as_ptr(), buf.as_mut_ptr() as *mut T, S); + } + + // `elements` have been moved into buf and will be droped by SmallVec + core::mem::forget(elements); + + // SAFETY: all the members in 0..S are initialized Self { - len: TaggedLen::new(N, false, Self::is_zst()), - raw: RawSmallVec::new_inline(MaybeUninit::new(buf)), + len: TaggedLen::new(S, false, Self::is_zst()), + raw: RawSmallVec::new_inline(buf), _marker: PhantomData, } }