@@ -673,11 +673,27 @@ impl<T, const N: usize> SmallVec<T, N> {
673673 }
674674
675675 #[ inline]
676- pub const fn from_buf ( buf : [ T ; N ] ) -> Self {
677- // SAFETY: all the members in 0..N are initialized
676+ pub const fn from_buf < const S : usize > ( elements : [ T ; S ] ) -> Self {
677+ assert ! ( S <= N ) ; // Free check since the values are known at compile time
678+
679+ // Althought we create a new buffer, since S and N are known at compile time,
680+ // even with `-C opt-level=1`, it gets optimized as best as it could be. (Checked with <godbolt.org>)
681+ let mut buf: MaybeUninit < [ T ; N ] > = MaybeUninit :: uninit ( ) ;
682+
683+ // SAFETY: buf and elements do not overlap, are aligned and have space
684+ // for at least S elements since S <= N.
685+ // We will drop the elements only once since we do forget(elements).
686+ unsafe {
687+ copy_nonoverlapping ( elements. as_ptr ( ) , buf. as_mut_ptr ( ) as * mut T , S ) ;
688+ }
689+
690+ // `elements` have been moved into buf and will be droped by SmallVec
691+ core:: mem:: forget ( elements) ;
692+
693+ // SAFETY: all the members in 0..S are initialized
678694 Self {
679- len : TaggedLen :: new ( N , false , Self :: is_zst ( ) ) ,
680- raw : RawSmallVec :: new_inline ( MaybeUninit :: new ( buf) ) ,
695+ len : TaggedLen :: new ( S , false , Self :: is_zst ( ) ) ,
696+ raw : RawSmallVec :: new_inline ( buf) ,
681697 _marker : PhantomData ,
682698 }
683699 }
0 commit comments