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