bytemuck/
zeroable.rs

1use super::*;
2
3/// Trait for types that can be safely created with
4/// [`zeroed`](core::mem::zeroed).
5///
6/// An all-zeroes value may or may not be the same value as the
7/// [Default](core::default::Default) value of the type.
8///
9/// ## Safety
10///
11/// * Your type must be inhabited (eg: no
12///   [Infallible](core::convert::Infallible)).
13/// * Your type must be allowed to be an "all zeroes" bit pattern (eg: no
14///   [`NonNull<T>`](core::ptr::NonNull)).
15///
16/// ## Features
17///
18/// Some `impl`s are feature gated due to the MSRV policy:
19///
20/// * `MaybeUninit<T>` was not available in 1.34.0, but is available under the
21///   `zeroable_maybe_uninit` feature flag.
22/// * `Atomic*` types require Rust 1.60.0 or later to work on certain platforms,
23///   but is available under the `zeroable_atomics` feature flag.
24/// * `[T; N]` for arbitrary `N` requires the `min_const_generics` feature flag.
25pub unsafe trait Zeroable: Sized {
26  /// Calls [`zeroed`](core::mem::zeroed).
27  ///
28  /// This is a trait method so that you can write `MyType::zeroed()` in your
29  /// code. It is a contract of this trait that if you implement it on your type
30  /// you **must not** override this method.
31  #[inline]
32  fn zeroed() -> Self {
33    unsafe { core::mem::zeroed() }
34  }
35}
36unsafe impl Zeroable for () {}
37unsafe impl Zeroable for bool {}
38unsafe impl Zeroable for char {}
39unsafe impl Zeroable for u8 {}
40unsafe impl Zeroable for i8 {}
41unsafe impl Zeroable for u16 {}
42unsafe impl Zeroable for i16 {}
43unsafe impl Zeroable for u32 {}
44unsafe impl Zeroable for i32 {}
45unsafe impl Zeroable for u64 {}
46unsafe impl Zeroable for i64 {}
47unsafe impl Zeroable for usize {}
48unsafe impl Zeroable for isize {}
49unsafe impl Zeroable for u128 {}
50unsafe impl Zeroable for i128 {}
51#[cfg(feature = "nightly_float")]
52unsafe impl Zeroable for f16 {}
53unsafe impl Zeroable for f32 {}
54unsafe impl Zeroable for f64 {}
55#[cfg(feature = "nightly_float")]
56unsafe impl Zeroable for f128 {}
57unsafe impl<T: Zeroable> Zeroable for Wrapping<T> {}
58unsafe impl<T: Zeroable> Zeroable for core::cmp::Reverse<T> {}
59
60// Note: we can't implement this for all `T: ?Sized` types because it would
61// create NULL pointers for vtables.
62// Maybe one day this could be changed to be implemented for
63// `T: ?Sized where <T as core::ptr::Pointee>::Metadata: Zeroable`.
64unsafe impl<T> Zeroable for *mut T {}
65unsafe impl<T> Zeroable for *const T {}
66unsafe impl<T> Zeroable for *mut [T] {}
67unsafe impl<T> Zeroable for *const [T] {}
68unsafe impl Zeroable for *mut str {}
69unsafe impl Zeroable for *const str {}
70
71unsafe impl<T: ?Sized> Zeroable for PhantomData<T> {}
72unsafe impl Zeroable for PhantomPinned {}
73unsafe impl<T: Zeroable> Zeroable for core::mem::ManuallyDrop<T> {}
74unsafe impl<T: Zeroable> Zeroable for core::cell::UnsafeCell<T> {}
75unsafe impl<T: Zeroable> Zeroable for core::cell::Cell<T> {}
76
77#[cfg(feature = "zeroable_atomics")]
78#[cfg_attr(feature = "nightly_docs", doc(cfg(feature = "zeroable_atomics")))]
79mod atomic_impls {
80  use super::Zeroable;
81
82  #[cfg(target_has_atomic = "8")]
83  unsafe impl Zeroable for core::sync::atomic::AtomicBool {}
84  #[cfg(target_has_atomic = "8")]
85  unsafe impl Zeroable for core::sync::atomic::AtomicU8 {}
86  #[cfg(target_has_atomic = "8")]
87  unsafe impl Zeroable for core::sync::atomic::AtomicI8 {}
88
89  #[cfg(target_has_atomic = "16")]
90  unsafe impl Zeroable for core::sync::atomic::AtomicU16 {}
91  #[cfg(target_has_atomic = "16")]
92  unsafe impl Zeroable for core::sync::atomic::AtomicI16 {}
93
94  #[cfg(target_has_atomic = "32")]
95  unsafe impl Zeroable for core::sync::atomic::AtomicU32 {}
96  #[cfg(target_has_atomic = "32")]
97  unsafe impl Zeroable for core::sync::atomic::AtomicI32 {}
98
99  #[cfg(target_has_atomic = "64")]
100  unsafe impl Zeroable for core::sync::atomic::AtomicU64 {}
101  #[cfg(target_has_atomic = "64")]
102  unsafe impl Zeroable for core::sync::atomic::AtomicI64 {}
103
104  #[cfg(target_has_atomic = "ptr")]
105  unsafe impl Zeroable for core::sync::atomic::AtomicUsize {}
106  #[cfg(target_has_atomic = "ptr")]
107  unsafe impl Zeroable for core::sync::atomic::AtomicIsize {}
108
109  #[cfg(target_has_atomic = "ptr")]
110  unsafe impl<T> Zeroable for core::sync::atomic::AtomicPtr<T> {}
111}
112
113#[cfg(feature = "zeroable_maybe_uninit")]
114#[cfg_attr(
115  feature = "nightly_docs",
116  doc(cfg(feature = "zeroable_maybe_uninit"))
117)]
118unsafe impl<T> Zeroable for core::mem::MaybeUninit<T> {}
119
120unsafe impl<A: Zeroable> Zeroable for (A,) {}
121unsafe impl<A: Zeroable, B: Zeroable> Zeroable for (A, B) {}
122unsafe impl<A: Zeroable, B: Zeroable, C: Zeroable> Zeroable for (A, B, C) {}
123unsafe impl<A: Zeroable, B: Zeroable, C: Zeroable, D: Zeroable> Zeroable
124  for (A, B, C, D)
125{
126}
127unsafe impl<A: Zeroable, B: Zeroable, C: Zeroable, D: Zeroable, E: Zeroable>
128  Zeroable for (A, B, C, D, E)
129{
130}
131unsafe impl<
132    A: Zeroable,
133    B: Zeroable,
134    C: Zeroable,
135    D: Zeroable,
136    E: Zeroable,
137    F: Zeroable,
138  > Zeroable for (A, B, C, D, E, F)
139{
140}
141unsafe impl<
142    A: Zeroable,
143    B: Zeroable,
144    C: Zeroable,
145    D: Zeroable,
146    E: Zeroable,
147    F: Zeroable,
148    G: Zeroable,
149  > Zeroable for (A, B, C, D, E, F, G)
150{
151}
152unsafe impl<
153    A: Zeroable,
154    B: Zeroable,
155    C: Zeroable,
156    D: Zeroable,
157    E: Zeroable,
158    F: Zeroable,
159    G: Zeroable,
160    H: Zeroable,
161  > Zeroable for (A, B, C, D, E, F, G, H)
162{
163}
164
165#[cfg(feature = "min_const_generics")]
166#[cfg_attr(feature = "nightly_docs", doc(cfg(feature = "min_const_generics")))]
167unsafe impl<T, const N: usize> Zeroable for [T; N] where T: Zeroable {}
168
169#[cfg(not(feature = "min_const_generics"))]
170impl_unsafe_marker_for_array!(
171  Zeroable, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
172  19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 48, 64, 96, 128, 256,
173  512, 1024, 2048, 4096
174);
175
176impl_unsafe_marker_for_simd!(
177  #[cfg(all(target_arch = "wasm32", feature = "wasm_simd"))]
178  unsafe impl Zeroable for wasm32::{v128}
179);
180
181impl_unsafe_marker_for_simd!(
182  #[cfg(all(target_arch = "aarch64", feature = "aarch64_simd"))]
183  unsafe impl Zeroable for aarch64::{
184    float32x2_t, float32x2x2_t, float32x2x3_t, float32x2x4_t, float32x4_t,
185    float32x4x2_t, float32x4x3_t, float32x4x4_t, float64x1_t, float64x1x2_t,
186    float64x1x3_t, float64x1x4_t, float64x2_t, float64x2x2_t, float64x2x3_t,
187    float64x2x4_t, int16x4_t, int16x4x2_t, int16x4x3_t, int16x4x4_t, int16x8_t,
188    int16x8x2_t, int16x8x3_t, int16x8x4_t, int32x2_t, int32x2x2_t, int32x2x3_t,
189    int32x2x4_t, int32x4_t, int32x4x2_t, int32x4x3_t, int32x4x4_t, int64x1_t,
190    int64x1x2_t, int64x1x3_t, int64x1x4_t, int64x2_t, int64x2x2_t, int64x2x3_t,
191    int64x2x4_t, int8x16_t, int8x16x2_t, int8x16x3_t, int8x16x4_t, int8x8_t,
192    int8x8x2_t, int8x8x3_t, int8x8x4_t, poly16x4_t, poly16x4x2_t, poly16x4x3_t,
193    poly16x4x4_t, poly16x8_t, poly16x8x2_t, poly16x8x3_t, poly16x8x4_t,
194    poly64x1_t, poly64x1x2_t, poly64x1x3_t, poly64x1x4_t, poly64x2_t,
195    poly64x2x2_t, poly64x2x3_t, poly64x2x4_t, poly8x16_t, poly8x16x2_t,
196    poly8x16x3_t, poly8x16x4_t, poly8x8_t, poly8x8x2_t, poly8x8x3_t, poly8x8x4_t,
197    uint16x4_t, uint16x4x2_t, uint16x4x3_t, uint16x4x4_t, uint16x8_t,
198    uint16x8x2_t, uint16x8x3_t, uint16x8x4_t, uint32x2_t, uint32x2x2_t,
199    uint32x2x3_t, uint32x2x4_t, uint32x4_t, uint32x4x2_t, uint32x4x3_t,
200    uint32x4x4_t, uint64x1_t, uint64x1x2_t, uint64x1x3_t, uint64x1x4_t,
201    uint64x2_t, uint64x2x2_t, uint64x2x3_t, uint64x2x4_t, uint8x16_t,
202    uint8x16x2_t, uint8x16x3_t, uint8x16x4_t, uint8x8_t, uint8x8x2_t,
203    uint8x8x3_t, uint8x8x4_t,
204  }
205);
206
207impl_unsafe_marker_for_simd!(
208  #[cfg(target_arch = "x86")]
209  unsafe impl Zeroable for x86::{
210    __m128i, __m128, __m128d,
211    __m256i, __m256, __m256d,
212  }
213);
214
215impl_unsafe_marker_for_simd!(
216  #[cfg(target_arch = "x86_64")]
217    unsafe impl Zeroable for x86_64::{
218        __m128i, __m128, __m128d,
219        __m256i, __m256, __m256d,
220    }
221);
222
223#[cfg(feature = "nightly_portable_simd")]
224#[cfg_attr(
225  feature = "nightly_docs",
226  doc(cfg(feature = "nightly_portable_simd"))
227)]
228unsafe impl<T, const N: usize> Zeroable for core::simd::Simd<T, N>
229where
230  T: core::simd::SimdElement + Zeroable,
231  core::simd::LaneCount<N>: core::simd::SupportedLaneCount,
232{
233}
234
235impl_unsafe_marker_for_simd!(
236  #[cfg(all(target_arch = "x86", feature = "nightly_stdsimd"))]
237  unsafe impl Zeroable for x86::{
238    __m128bh, __m256bh, __m512,
239    __m512bh, __m512d, __m512i,
240  }
241);
242
243impl_unsafe_marker_for_simd!(
244  #[cfg(all(target_arch = "x86_64", feature = "nightly_stdsimd"))]
245  unsafe impl Zeroable for x86_64::{
246    __m128bh, __m256bh, __m512,
247    __m512bh, __m512d, __m512i,
248  }
249);