@@ -109,12 +109,13 @@ impl core::fmt::Display for CollectionAllocErr {
109109/// Either a stack array with `length <= N` or a heap array
110110/// whose pointer and capacity are stored here.
111111///
112- /// We store a `*const T` instead of a `*mut T` so that the type is covariant
112+ /// We store a `NonNull<T>` instead of a `*mut T`, so that
113+ /// niche-optimization can be performed and the type is covariant
113114/// with respect to `T`.
114115#[ repr( C ) ]
115116pub union RawSmallVec < T , const N : usize > {
116117 inline : ManuallyDrop < MaybeUninit < [ T ; N ] > > ,
117- heap : ( * const T , usize ) , // this pointer is never null
118+ heap : ( NonNull < T > , usize ) ,
118119}
119120
120121#[ inline]
@@ -143,7 +144,7 @@ impl<T, const N: usize> RawSmallVec<T, N> {
143144 }
144145 }
145146 #[ inline]
146- const fn new_heap ( ptr : * mut T , capacity : usize ) -> Self {
147+ const fn new_heap ( ptr : NonNull < T > , capacity : usize ) -> Self {
147148 Self {
148149 heap : ( ptr, capacity) ,
149150 }
@@ -168,15 +169,15 @@ impl<T, const N: usize> RawSmallVec<T, N> {
168169 /// The vector must be on the heap
169170 #[ inline]
170171 const unsafe fn as_ptr_heap ( & self ) -> * const T {
171- self . heap . 0
172+ self . heap . 0 . as_ptr ( )
172173 }
173174
174175 /// # Safety
175176 ///
176177 /// The vector must be on the heap
177178 #[ inline]
178179 unsafe fn as_mut_ptr_heap ( & mut self ) -> * mut T {
179- self . heap . 0 as * mut T
180+ self . heap . 0 . as_ptr ( )
180181 }
181182
182183 /// # Safety
@@ -216,7 +217,7 @@ impl<T, const N: usize> RawSmallVec<T, N> {
216217 Err ( CollectionAllocErr :: AllocErr { layout : new_layout } )
217218 } else {
218219 copy_nonoverlapping ( ptr, new_ptr, len) ;
219- * self = Self :: new_heap ( new_ptr, new_capacity) ;
220+ * self = Self :: new_heap ( NonNull :: new_unchecked ( new_ptr) , new_capacity) ;
220221 Ok ( ( ) )
221222 }
222223 } else {
@@ -236,7 +237,7 @@ impl<T, const N: usize> RawSmallVec<T, N> {
236237 if new_ptr. is_null ( ) {
237238 Err ( CollectionAllocErr :: AllocErr { layout : new_layout } )
238239 } else {
239- * self = Self :: new_heap ( new_ptr, new_capacity) ;
240+ * self = Self :: new_heap ( NonNull :: new_unchecked ( new_ptr) , new_capacity) ;
240241 Ok ( ( ) )
241242 }
242243 }
@@ -733,7 +734,9 @@ impl<T, const N: usize> SmallVec<T, N> {
733734 let mut vec = ManuallyDrop :: new ( vec) ;
734735 let len = vec. len ( ) ;
735736 let cap = vec. capacity ( ) ;
736- let ptr = vec. as_mut_ptr ( ) ;
737+ // SAFETY: vec.capacity is not `0` (checked above), so the pointer
738+ // can not dangle and thus specifically cannot be null.
739+ let ptr = unsafe { NonNull :: new_unchecked ( vec. as_mut_ptr ( ) ) } ;
737740
738741 Self {
739742 len : TaggedLen :: new ( len, true , Self :: is_zst ( ) ) ,
@@ -1002,11 +1005,10 @@ impl<T, const N: usize> SmallVec<T, N> {
10021005 debug_assert ! ( self . spilled( ) ) ;
10031006 let len = self . len ( ) ;
10041007 let ( ptr, cap) = self . raw . heap ;
1005- let ptr = ptr as * mut T ;
10061008 if len == cap {
10071009 self . reserve ( 1 ) ;
10081010 }
1009- ptr. add ( len) . write ( value) ;
1011+ ptr. as_ptr ( ) . add ( len) . write ( value) ;
10101012 self . set_len ( len + 1 )
10111013 }
10121014
@@ -1076,9 +1078,9 @@ impl<T, const N: usize> SmallVec<T, N> {
10761078
10771079 // SAFETY: len <= new_capacity <= Self::inline_size()
10781080 // so the copy is within bounds of the inline member
1079- copy_nonoverlapping ( ptr, self . raw . as_mut_ptr_inline ( ) , len) ;
1081+ copy_nonoverlapping ( ptr. as_ptr ( ) , self . raw . as_mut_ptr_inline ( ) , len) ;
10801082 drop ( DropDealloc {
1081- ptr : NonNull :: new_unchecked ( ptr as * mut u8 ) ,
1083+ ptr : NonNull :: new_unchecked ( ptr. cast ( ) . as_ptr ( ) ) ,
10821084 size_bytes : old_cap * size_of :: < T > ( ) ,
10831085 align : align_of :: < T > ( ) ,
10841086 } ) ;
@@ -1154,10 +1156,10 @@ impl<T, const N: usize> SmallVec<T, N> {
11541156 unsafe {
11551157 let ( ptr, capacity) = self . raw . heap ;
11561158 self . raw = RawSmallVec :: new_inline ( MaybeUninit :: uninit ( ) ) ;
1157- copy_nonoverlapping ( ptr, self . raw . as_mut_ptr_inline ( ) , len) ;
1159+ copy_nonoverlapping ( ptr. as_ptr ( ) , self . raw . as_mut_ptr_inline ( ) , len) ;
11581160 self . set_inline ( ) ;
11591161 alloc:: alloc:: dealloc (
1160- ptr as * mut T as * mut u8 ,
1162+ ptr. cast ( ) . as_ptr ( ) ,
11611163 Layout :: from_size_align_unchecked ( capacity * size_of :: < T > ( ) , align_of :: < T > ( ) ) ,
11621164 ) ;
11631165 }
@@ -1333,10 +1335,16 @@ impl<T, const N: usize> SmallVec<T, N> {
13331335 vec
13341336 } else {
13351337 let this = ManuallyDrop :: new ( self ) ;
1336- // SAFETY: ptr was created with the global allocator
1338+ // SAFETY:
1339+ // - `ptr` was created with the global allocator
1340+ // - `ptr` was created with the appropriate alignment for `T`
1341+ // - the allocation pointed to by ptr is exactly cap * sizeof(T)
1342+ // - `len` is less than or equal to `cap`
1343+ // - the first `len` entries are proper `T`-values
1344+ // - the allocation is not larger than `isize::MAX`
13371345 unsafe {
13381346 let ( ptr, cap) = this. raw . heap ;
1339- Vec :: from_raw_parts ( ptr as * mut T , len, cap)
1347+ Vec :: from_raw_parts ( ptr. as_ptr ( ) , len, cap)
13401348 }
13411349 }
13421350 }
@@ -1510,6 +1518,14 @@ impl<T, const N: usize> SmallVec<T, N> {
15101518 #[ inline]
15111519 pub unsafe fn from_raw_parts ( ptr : * mut T , length : usize , capacity : usize ) -> SmallVec < T , N > {
15121520 assert ! ( !Self :: is_zst( ) ) ;
1521+
1522+ // SAFETY: We require caller to provide same ptr as we alloc
1523+ // and we never alloc null pointer.
1524+ let ptr = unsafe {
1525+ debug_assert ! ( !ptr. is_null( ) , "Called `from_raw_parts` with null pointer." ) ;
1526+ NonNull :: new_unchecked ( ptr)
1527+ } ;
1528+
15131529 SmallVec {
15141530 len : TaggedLen :: new ( length, true , Self :: is_zst ( ) ) ,
15151531 raw : RawSmallVec :: new_heap ( ptr, capacity) ,
@@ -1548,7 +1564,7 @@ impl<T, const N: usize> SmallVec<T, N> {
15481564 }
15491565 let len = self . len ( ) ;
15501566 let ( ptr, capacity) = self . raw . heap ;
1551- let ptr = ptr as * mut T ;
1567+ let ptr = ptr. as_ptr ( ) ;
15521568 // SAFETY: ptr is valid for `capacity - len` writes
15531569 let count = extend_batch ( ptr, capacity - len, len, & mut iter) ;
15541570 self . set_len ( len + count) ;
0 commit comments