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