@@ -109,12 +109,13 @@ impl core::fmt::Display for CollectionAllocErr {
109
109
/// Either a stack array with `length <= N` or a heap array
110
110
/// whose pointer and capacity are stored here.
111
111
///
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
113
114
/// with respect to `T`.
114
115
#[ repr( C ) ]
115
116
pub union RawSmallVec < T , const N : usize > {
116
117
inline : ManuallyDrop < MaybeUninit < [ T ; N ] > > ,
117
- heap : ( * const T , usize ) , // this pointer is never null
118
+ heap : ( NonNull < T > , usize ) ,
118
119
}
119
120
120
121
#[ inline]
@@ -143,7 +144,7 @@ impl<T, const N: usize> RawSmallVec<T, N> {
143
144
}
144
145
}
145
146
#[ inline]
146
- const fn new_heap ( ptr : * mut T , capacity : usize ) -> Self {
147
+ const fn new_heap ( ptr : NonNull < T > , capacity : usize ) -> Self {
147
148
Self {
148
149
heap : ( ptr, capacity) ,
149
150
}
@@ -168,15 +169,15 @@ impl<T, const N: usize> RawSmallVec<T, N> {
168
169
/// The vector must be on the heap
169
170
#[ inline]
170
171
const unsafe fn as_ptr_heap ( & self ) -> * const T {
171
- self . heap . 0
172
+ self . heap . 0 . as_ptr ( )
172
173
}
173
174
174
175
/// # Safety
175
176
///
176
177
/// The vector must be on the heap
177
178
#[ inline]
178
179
unsafe fn as_mut_ptr_heap ( & mut self ) -> * mut T {
179
- self . heap . 0 as * mut T
180
+ self . heap . 0 . as_ptr ( )
180
181
}
181
182
182
183
/// # Safety
@@ -216,7 +217,7 @@ impl<T, const N: usize> RawSmallVec<T, N> {
216
217
Err ( CollectionAllocErr :: AllocErr { layout : new_layout } )
217
218
} else {
218
219
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) ;
220
221
Ok ( ( ) )
221
222
}
222
223
} else {
@@ -236,7 +237,7 @@ impl<T, const N: usize> RawSmallVec<T, N> {
236
237
if new_ptr. is_null ( ) {
237
238
Err ( CollectionAllocErr :: AllocErr { layout : new_layout } )
238
239
} else {
239
- * self = Self :: new_heap ( new_ptr, new_capacity) ;
240
+ * self = Self :: new_heap ( NonNull :: new_unchecked ( new_ptr) , new_capacity) ;
240
241
Ok ( ( ) )
241
242
}
242
243
}
@@ -733,7 +734,9 @@ impl<T, const N: usize> SmallVec<T, N> {
733
734
let mut vec = ManuallyDrop :: new ( vec) ;
734
735
let len = vec. len ( ) ;
735
736
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 ( ) ) } ;
737
740
738
741
Self {
739
742
len : TaggedLen :: new ( len, true , Self :: is_zst ( ) ) ,
@@ -1002,11 +1005,10 @@ impl<T, const N: usize> SmallVec<T, N> {
1002
1005
debug_assert ! ( self . spilled( ) ) ;
1003
1006
let len = self . len ( ) ;
1004
1007
let ( ptr, cap) = self . raw . heap ;
1005
- let ptr = ptr as * mut T ;
1006
1008
if len == cap {
1007
1009
self . reserve ( 1 ) ;
1008
1010
}
1009
- ptr. add ( len) . write ( value) ;
1011
+ ptr. as_ptr ( ) . add ( len) . write ( value) ;
1010
1012
self . set_len ( len + 1 )
1011
1013
}
1012
1014
@@ -1076,9 +1078,9 @@ impl<T, const N: usize> SmallVec<T, N> {
1076
1078
1077
1079
// SAFETY: len <= new_capacity <= Self::inline_size()
1078
1080
// 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) ;
1080
1082
drop ( DropDealloc {
1081
- ptr : NonNull :: new_unchecked ( ptr as * mut u8 ) ,
1083
+ ptr : NonNull :: new_unchecked ( ptr. cast ( ) . as_ptr ( ) ) ,
1082
1084
size_bytes : old_cap * size_of :: < T > ( ) ,
1083
1085
align : align_of :: < T > ( ) ,
1084
1086
} ) ;
@@ -1154,10 +1156,10 @@ impl<T, const N: usize> SmallVec<T, N> {
1154
1156
unsafe {
1155
1157
let ( ptr, capacity) = self . raw . heap ;
1156
1158
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) ;
1158
1160
self . set_inline ( ) ;
1159
1161
alloc:: alloc:: dealloc (
1160
- ptr as * mut T as * mut u8 ,
1162
+ ptr. cast ( ) . as_ptr ( ) ,
1161
1163
Layout :: from_size_align_unchecked ( capacity * size_of :: < T > ( ) , align_of :: < T > ( ) ) ,
1162
1164
) ;
1163
1165
}
@@ -1333,10 +1335,16 @@ impl<T, const N: usize> SmallVec<T, N> {
1333
1335
vec
1334
1336
} else {
1335
1337
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`
1337
1345
unsafe {
1338
1346
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)
1340
1348
}
1341
1349
}
1342
1350
}
@@ -1510,6 +1518,14 @@ impl<T, const N: usize> SmallVec<T, N> {
1510
1518
#[ inline]
1511
1519
pub unsafe fn from_raw_parts ( ptr : * mut T , length : usize , capacity : usize ) -> SmallVec < T , N > {
1512
1520
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
+
1513
1529
SmallVec {
1514
1530
len : TaggedLen :: new ( length, true , Self :: is_zst ( ) ) ,
1515
1531
raw : RawSmallVec :: new_heap ( ptr, capacity) ,
@@ -1548,7 +1564,7 @@ impl<T, const N: usize> SmallVec<T, N> {
1548
1564
}
1549
1565
let len = self . len ( ) ;
1550
1566
let ( ptr, capacity) = self . raw . heap ;
1551
- let ptr = ptr as * mut T ;
1567
+ let ptr = ptr. as_ptr ( ) ;
1552
1568
// SAFETY: ptr is valid for `capacity - len` writes
1553
1569
let count = extend_batch ( ptr, capacity - len, len, & mut iter) ;
1554
1570
self . set_len ( len + count) ;
0 commit comments