1 use crate::Pod; 2 use core::num::{ 3 NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, 4 NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, 5 }; 6 7 /// Marker trait for "plain old data" types with no uninit (or padding) bytes. 8 /// 9 /// The requirements for this is very similar to [`Pod`], 10 /// except that it doesn't require that all bit patterns of the type are valid, 11 /// i.e. it does not require the type to be [`Zeroable`][crate::Zeroable]. 12 /// This limits what you can do with a type of this kind, but also broadens the 13 /// included types to things like C-style enums. Notably, you can only cast from 14 /// *immutable* references to a [`NoUninit`] type into *immutable* references of 15 /// any other type, no casting of mutable references or mutable references to 16 /// slices etc. 17 /// 18 /// [`Pod`] is a subset of [`NoUninit`], meaning that any `T: Pod` is also 19 /// [`NoUninit`] but any `T: NoUninit` is not necessarily [`Pod`]. If possible, 20 /// prefer implementing [`Pod`] directly. To get more [`Pod`]-like functionality 21 /// for a type that is only [`NoUninit`], consider also implementing 22 /// [`CheckedBitPattern`][crate::CheckedBitPattern]. 23 /// 24 /// # Derive 25 /// 26 /// A `#[derive(NoUninit)]` macro is provided under the `derive` feature flag 27 /// which will automatically validate the requirements of this trait and 28 /// implement the trait for you for both enums and structs. This is the 29 /// recommended method for implementing the trait, however it's also possible to 30 /// do manually. If you implement it manually, you *must* carefully follow the 31 /// below safety rules. 32 /// 33 /// # Safety 34 /// 35 /// The same as [`Pod`] except we disregard the rule about it must 36 /// allow any bit pattern (i.e. it does not need to be 37 /// [`Zeroable`][crate::Zeroable]). Still, this is a quite strong guarantee 38 /// about a type, so *be careful* whem implementing it manually. 39 /// 40 /// * The type must be inhabited (eg: no 41 /// [Infallible](core::convert::Infallible)). 42 /// * The type must not contain any uninit (or padding) bytes, either in the 43 /// middle or on the end (eg: no `#[repr(C)] struct Foo(u8, u16)`, which has 44 /// padding in the middle, and also no `#[repr(C)] struct Foo(u16, u8)`, which 45 /// has padding on the end). 46 /// * Structs need to have all fields also be `NoUninit`. 47 /// * Structs need to be `repr(C)` or `repr(transparent)`. In the case of 48 /// `repr(C)`, the `packed` and `align` repr modifiers can be used as long as 49 /// all other rules end up being followed. 50 /// * Enums need to have an explicit `#[repr(Int)]` 51 /// * Enums must have only fieldless variants 52 /// * It is disallowed for types to contain pointer types, `Cell`, `UnsafeCell`, 53 /// atomics, and any other forms of interior mutability. 54 /// * More precisely: A shared reference to the type must allow reads, and 55 /// *only* reads. RustBelt's separation logic is based on the notion that a 56 /// type is allowed to define a sharing predicate, its own invariant that must 57 /// hold for shared references, and this predicate is the reasoning that allow 58 /// it to deal with atomic and cells etc. We require the sharing predicate to 59 /// be trivial and permit only read-only access. 60 /// * There's probably more, don't mess it up (I mean it). 61 pub unsafe trait NoUninit: Sized + Copy + 'static {} 62 63 unsafe impl<T: Pod> NoUninit for T {} 64 65 unsafe impl NoUninit for char {} 66 67 unsafe impl NoUninit for bool {} 68 69 unsafe impl NoUninit for NonZeroU8 {} 70 unsafe impl NoUninit for NonZeroI8 {} 71 unsafe impl NoUninit for NonZeroU16 {} 72 unsafe impl NoUninit for NonZeroI16 {} 73 unsafe impl NoUninit for NonZeroU32 {} 74 unsafe impl NoUninit for NonZeroI32 {} 75 unsafe impl NoUninit for NonZeroU64 {} 76 unsafe impl NoUninit for NonZeroI64 {} 77 unsafe impl NoUninit for NonZeroU128 {} 78 unsafe impl NoUninit for NonZeroI128 {} 79 unsafe impl NoUninit for NonZeroUsize {} 80 unsafe impl NoUninit for NonZeroIsize {} 81