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 | |