@@ -195,8 +195,14 @@ use crate::{
195
195
} ;
196
196
use alloc:: boxed:: Box ;
197
197
use core:: {
198
- alloc:: AllocError , cell:: Cell , convert:: Infallible , marker:: PhantomData , mem:: MaybeUninit ,
199
- pin:: Pin , ptr,
198
+ alloc:: AllocError ,
199
+ cell:: Cell ,
200
+ convert:: Infallible ,
201
+ marker:: PhantomData ,
202
+ mem:: MaybeUninit ,
203
+ num:: * ,
204
+ pin:: Pin ,
205
+ ptr:: { self , NonNull } ,
200
206
} ;
201
207
202
208
#[ doc( hidden) ]
@@ -1323,3 +1329,90 @@ pub unsafe trait PinnedDrop: __internal::HasPinData {
1323
1329
/// automatically.
1324
1330
fn drop ( self : Pin < & mut Self > , only_call_from_drop : __internal:: OnlyCallFromDrop ) ;
1325
1331
}
1332
+
1333
+ /// Marker trait for types that can be initialized by writing just zeroes.
1334
+ ///
1335
+ /// # Safety
1336
+ ///
1337
+ /// The bit pattern consisting of only zeroes is a valid bit pattern for this type. In other words,
1338
+ /// this is not UB:
1339
+ ///
1340
+ /// ```rust,ignore
1341
+ /// let val: Self = unsafe { core::mem::zeroed() };
1342
+ /// ```
1343
+ pub unsafe trait Zeroable { }
1344
+
1345
+ /// Create a new zeroed T.
1346
+ ///
1347
+ /// The returned initializer will write `0x00` to every byte of the given `slot`.
1348
+ #[ inline]
1349
+ pub fn zeroed < T : Zeroable > ( ) -> impl Init < T > {
1350
+ // SAFETY: Because `T: Zeroable`, all bytes zero is a valid bit pattern for `T`
1351
+ // and because we write all zeroes, the memory is initialized.
1352
+ unsafe {
1353
+ init_from_closure ( |slot : * mut T | {
1354
+ slot. write_bytes ( 0 , 1 ) ;
1355
+ Ok ( ( ) )
1356
+ } )
1357
+ }
1358
+ }
1359
+
1360
+ macro_rules! impl_zeroable {
1361
+ ( $( $( { $( $generics: tt) * } ) ? $t: ty, ) * ) => {
1362
+ $( unsafe impl $( $( $generics) * ) ? Zeroable for $t { } ) *
1363
+ } ;
1364
+ }
1365
+
1366
+ impl_zeroable ! {
1367
+ // SAFETY: All primitives that are allowed to be zero.
1368
+ bool ,
1369
+ char ,
1370
+ u8 , u16 , u32 , u64 , u128 , usize ,
1371
+ i8 , i16 , i32 , i64 , i128 , isize ,
1372
+ f32 , f64 ,
1373
+
1374
+ // SAFETY: These are ZSTs, there is nothing to zero.
1375
+ { <T : ?Sized >} PhantomData <T >, core:: marker:: PhantomPinned , Infallible , ( ) ,
1376
+
1377
+ // SAFETY: Type is allowed to take any value, including all zeros.
1378
+ { <T >} MaybeUninit <T >,
1379
+
1380
+ // SAFETY: All zeros is equivalent to `None` (option layout optimization guarantee).
1381
+ Option <NonZeroU8 >, Option <NonZeroU16 >, Option <NonZeroU32 >, Option <NonZeroU64 >,
1382
+ Option <NonZeroU128 >, Option <NonZeroUsize >,
1383
+ Option <NonZeroI8 >, Option <NonZeroI16 >, Option <NonZeroI32 >, Option <NonZeroI64 >,
1384
+ Option <NonZeroI128 >, Option <NonZeroIsize >,
1385
+
1386
+ // SAFETY: All zeros is equivalent to `None` (option layout optimization guarantee).
1387
+ //
1388
+ // In this case we are allowed to use `T: ?Sized`, since all zeros is the `None` variant.
1389
+ { <T : ?Sized >} Option <NonNull <T >>,
1390
+ { <T : ?Sized >} Option <Box <T >>,
1391
+
1392
+ // SAFETY: `null` pointer is valid.
1393
+ //
1394
+ // We cannot use `T: ?Sized`, since the VTABLE pointer part of fat pointers is not allowed to be
1395
+ // null.
1396
+ //
1397
+ // When `Pointee` gets stabilized, we could use
1398
+ // `T: ?Sized where <T as Pointee>::Metadata: Zeroable`
1399
+ { <T >} * mut T , { <T >} * const T ,
1400
+
1401
+ // SAFETY: `null` pointer is valid and the metadata part of these fat pointers is allowed to be
1402
+ // zero.
1403
+ { <T >} * mut [ T ] , { <T >} * const [ T ] , * mut str , * const str ,
1404
+
1405
+ // SAFETY: `T` is `Zeroable`.
1406
+ { <const N : usize , T : Zeroable >} [ T ; N ] , { <T : Zeroable >} Wrapping <T >,
1407
+ }
1408
+
1409
+ macro_rules! impl_tuple_zeroable {
1410
+ ( $( , ) ?) => { } ;
1411
+ ( $first: ident, $( $t: ident) ,* $( , ) ?) => {
1412
+ // SAFETY: All elements are zeroable and padding can be zero.
1413
+ unsafe impl <$first: Zeroable , $( $t: Zeroable ) ,* > Zeroable for ( $first, $( $t) ,* ) { }
1414
+ impl_tuple_zeroable!( $( $t) ,* , ) ;
1415
+ }
1416
+ }
1417
+
1418
+ impl_tuple_zeroable ! ( A , B , C , D , E , F , G , H , I , J ) ;
0 commit comments