@@ -673,11 +673,27 @@ impl<T, const N: usize> SmallVec<T, N> {
673
673
}
674
674
675
675
#[ 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
678
694
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) ,
681
697
_marker : PhantomData ,
682
698
}
683
699
}
0 commit comments