@@ -34,6 +34,7 @@ use core::cmp::Ordering;
3434use core:: hash:: Hash ;
3535use core:: iter:: { Chain , FusedIterator } ;
3636use core:: mem:: ManuallyDrop ;
37+ use core:: mem:: MaybeUninit ;
3738use core:: ops:: { BitAnd , BitAndAssign , BitOr , BitOrAssign , BitXor , BitXorAssign , Index } ;
3839use core:: ptr:: NonNull ;
3940pub use range:: IndexRange ;
@@ -70,7 +71,7 @@ fn vec_into_parts<T>(vec: Vec<T>) -> (NonNull<T>, usize, usize) {
7071/// [0,1,0].
7172#[ derive( Debug , Eq ) ]
7273pub struct FixedBitSet {
73- pub ( crate ) data : NonNull < SimdBlock > ,
74+ pub ( crate ) data : NonNull < MaybeUninit < SimdBlock > > ,
7475 capacity : usize ,
7576 /// length in bits
7677 pub ( crate ) length : usize ,
@@ -104,7 +105,7 @@ impl FixedBitSet {
104105 fn from_blocks_and_len ( data : Vec < SimdBlock > , length : usize ) -> Self {
105106 let ( data, capacity, _) = vec_into_parts ( data) ;
106107 FixedBitSet {
107- data,
108+ data : data . cast ( ) ,
108109 capacity,
109110 length,
110111 }
@@ -134,17 +135,32 @@ impl FixedBitSet {
134135 /// Grow capacity to **bits**, all new bits initialized to zero
135136 #[ inline]
136137 pub fn grow ( & mut self , bits : usize ) {
137- if bits <= self . length {
138- return ;
138+ #[ cold]
139+ #[ track_caller]
140+ #[ inline( never) ]
141+ fn do_grow ( slf : & mut FixedBitSet , bits : usize ) {
142+ // SAFETY: The provided fill is initialized to NONE.
143+ unsafe { slf. grow_inner ( bits, MaybeUninit :: new ( SimdBlock :: NONE ) ) } ;
139144 }
145+
146+ if bits > self . length {
147+ do_grow ( self , bits) ;
148+ }
149+ }
150+
151+ /// # Safety
152+ /// If `fill` is uninitialized, the memory must not be accessed and must be immediately
153+ /// written over
154+ #[ inline( always) ]
155+ unsafe fn grow_inner ( & mut self , bits : usize , fill : MaybeUninit < SimdBlock > ) {
140156 // SAFETY: The data pointer and capacity were created from a Vec initially. The block
141157 // len is identical to that of the original.
142158 let mut data = unsafe {
143159 Vec :: from_raw_parts ( self . data . as_ptr ( ) , self . simd_block_len ( ) , self . capacity )
144160 } ;
145161 let ( mut blocks, rem) = div_rem ( bits, SimdBlock :: BITS ) ;
146162 blocks += ( rem > 0 ) as usize ;
147- data. resize ( blocks, SimdBlock :: NONE ) ;
163+ data. resize ( blocks, fill ) ;
148164 let ( data, capacity, _) = vec_into_parts ( data) ;
149165 self . data = data;
150166 self . capacity = capacity;
@@ -184,11 +200,25 @@ impl FixedBitSet {
184200 fn as_simd_slice ( & self ) -> & [ SimdBlock ] {
185201 // SAFETY: The slice constructed is within bounds of the underlying allocation. This function
186202 // is called with a read-only borrow so no other write can happen as long as the returned borrow lives.
187- unsafe { core:: slice:: from_raw_parts ( self . data . as_ptr ( ) , self . simd_block_len ( ) ) }
203+ unsafe { core:: slice:: from_raw_parts ( self . data . as_ptr ( ) . cast ( ) , self . simd_block_len ( ) ) }
188204 }
189205
190206 #[ inline]
191207 fn as_mut_simd_slice ( & mut self ) -> & mut [ SimdBlock ] {
208+ // SAFETY: The slice constructed is within bounds of the underlying allocation. This function
209+ // is called with a mutable borrow so no other read or write can happen as long as the returned borrow lives.
210+ unsafe { core:: slice:: from_raw_parts_mut ( self . data . as_ptr ( ) . cast ( ) , self . simd_block_len ( ) ) }
211+ }
212+
213+ #[ inline]
214+ fn as_simd_slice_uninit ( & self ) -> & [ MaybeUninit < SimdBlock > ] {
215+ // SAFETY: The slice constructed is within bounds of the underlying allocation. This function
216+ // is called with a read-only borrow so no other write can happen as long as the returned borrow lives.
217+ unsafe { core:: slice:: from_raw_parts ( self . data . as_ptr ( ) , self . simd_block_len ( ) ) }
218+ }
219+
220+ #[ inline]
221+ fn as_mut_simd_slice_uninit ( & mut self ) -> & mut [ MaybeUninit < SimdBlock > ] {
192222 // SAFETY: The slice constructed is within bounds of the underlying allocation. This function
193223 // is called with a mutable borrow so no other read or write can happen as long as the returned borrow lives.
194224 unsafe { core:: slice:: from_raw_parts_mut ( self . data . as_ptr ( ) , self . simd_block_len ( ) ) }
@@ -758,8 +788,12 @@ impl FixedBitSet {
758788 let slice = unsafe { core:: slice:: from_raw_parts ( ptr, len) } ;
759789 // SAFETY: The data pointer and capacity were created from a Vec initially. The block
760790 // len is identical to that of the original.
761- let data = unsafe {
762- Vec :: from_raw_parts ( self . data . as_ptr ( ) , self . simd_block_len ( ) , self . capacity )
791+ let data: Vec < SimdBlock > = unsafe {
792+ Vec :: from_raw_parts (
793+ self . data . as_ptr ( ) . cast ( ) ,
794+ self . simd_block_len ( ) ,
795+ self . capacity ,
796+ )
763797 } ;
764798 let mut iter = slice. iter ( ) . copied ( ) ;
765799
@@ -1409,27 +1443,24 @@ impl Clone for FixedBitSet {
14091443
14101444 #[ inline]
14111445 fn clone_from ( & mut self , source : & Self ) {
1412- {
1413- let me = self . as_mut_simd_slice ( ) ;
1414- let them = source. as_simd_slice ( ) ;
1415- match me. len ( ) . cmp ( & them. len ( ) ) {
1416- Ordering :: Greater => {
1417- let ( head, tail) = me. split_at_mut ( them. len ( ) ) ;
1418- head. copy_from_slice ( them) ;
1419- tail. fill ( SimdBlock :: NONE ) ;
1420- self . length = source. length ;
1421- return ;
1422- }
1423- Ordering :: Equal => {
1424- me. copy_from_slice ( them) ;
1425- self . length = source. length ;
1426- return ;
1427- }
1428- // Self is smaller than the source, this requires allocation.
1429- Ordering :: Less => { }
1446+ if self . length < source. length {
1447+ // SAFETY: `fill` is uninitialized, but is immediately initialized from `source`.
1448+ unsafe { self . grow_inner ( source. length , MaybeUninit :: uninit ( ) ) } ;
1449+ }
1450+ let me = self . as_mut_simd_slice_uninit ( ) ;
1451+ let them = source. as_simd_slice_uninit ( ) ;
1452+ match me. len ( ) . cmp ( & them. len ( ) ) {
1453+ Ordering :: Greater => {
1454+ let ( head, tail) = me. split_at_mut ( them. len ( ) ) ;
1455+ head. copy_from_slice ( them) ;
1456+ tail. fill ( MaybeUninit :: new ( SimdBlock :: NONE ) ) ;
14301457 }
1458+ Ordering :: Equal => me. copy_from_slice ( them) ,
1459+ // The grow_inner above ensures that self is at least as large as source.
1460+ // so this branch is unreachable.
1461+ Ordering :: Less => { }
14311462 }
1432- * self = source. clone ( ) ;
1463+ self . length = source. length ;
14331464 }
14341465}
14351466
0 commit comments