]> git.proxmox.com Git - rustc.git/blob - library/alloc/src/vec/is_zero.rs
New upstream version 1.54.0+dfsg1
[rustc.git] / library / alloc / src / vec / is_zero.rs
1 use crate::boxed::Box;
2
3 #[rustc_specialization_trait]
4 pub(super) unsafe trait IsZero {
5 /// Whether this value is zero
6 fn is_zero(&self) -> bool;
7 }
8
9 macro_rules! impl_is_zero {
10 ($t:ty, $is_zero:expr) => {
11 unsafe impl IsZero for $t {
12 #[inline]
13 fn is_zero(&self) -> bool {
14 $is_zero(*self)
15 }
16 }
17 };
18 }
19
20 impl_is_zero!(i16, |x| x == 0);
21 impl_is_zero!(i32, |x| x == 0);
22 impl_is_zero!(i64, |x| x == 0);
23 impl_is_zero!(i128, |x| x == 0);
24 impl_is_zero!(isize, |x| x == 0);
25
26 impl_is_zero!(u16, |x| x == 0);
27 impl_is_zero!(u32, |x| x == 0);
28 impl_is_zero!(u64, |x| x == 0);
29 impl_is_zero!(u128, |x| x == 0);
30 impl_is_zero!(usize, |x| x == 0);
31
32 impl_is_zero!(bool, |x| x == false);
33 impl_is_zero!(char, |x| x == '\0');
34
35 impl_is_zero!(f32, |x: f32| x.to_bits() == 0);
36 impl_is_zero!(f64, |x: f64| x.to_bits() == 0);
37
38 unsafe impl<T> IsZero for *const T {
39 #[inline]
40 fn is_zero(&self) -> bool {
41 (*self).is_null()
42 }
43 }
44
45 unsafe impl<T> IsZero for *mut T {
46 #[inline]
47 fn is_zero(&self) -> bool {
48 (*self).is_null()
49 }
50 }
51
52 // `Option<&T>` and `Option<Box<T>>` are guaranteed to represent `None` as null.
53 // For fat pointers, the bytes that would be the pointer metadata in the `Some`
54 // variant are padding in the `None` variant, so ignoring them and
55 // zero-initializing instead is ok.
56 // `Option<&mut T>` never implements `Clone`, so there's no need for an impl of
57 // `SpecFromElem`.
58
59 unsafe impl<T: ?Sized> IsZero for Option<&T> {
60 #[inline]
61 fn is_zero(&self) -> bool {
62 self.is_none()
63 }
64 }
65
66 unsafe impl<T: ?Sized> IsZero for Option<Box<T>> {
67 #[inline]
68 fn is_zero(&self) -> bool {
69 self.is_none()
70 }
71 }
72
73 // `Option<num::NonZeroU32>` and similar have a representation guarantee that
74 // they're the same size as the corresponding `u32` type, as well as a guarantee
75 // that transmuting between `NonZeroU32` and `Option<num::NonZeroU32>` works.
76 // While the documentation officially makes it UB to transmute from `None`,
77 // we're the standard library so we can make extra inferences, and we know that
78 // the only niche available to represent `None` is the one that's all zeros.
79
80 macro_rules! impl_is_zero_option_of_nonzero {
81 ($($t:ident,)+) => {$(
82 unsafe impl IsZero for Option<core::num::$t> {
83 #[inline]
84 fn is_zero(&self) -> bool {
85 self.is_none()
86 }
87 }
88 )+};
89 }
90
91 impl_is_zero_option_of_nonzero!(
92 NonZeroU8,
93 NonZeroU16,
94 NonZeroU32,
95 NonZeroU64,
96 NonZeroU128,
97 NonZeroI8,
98 NonZeroI16,
99 NonZeroI32,
100 NonZeroI64,
101 NonZeroI128,
102 NonZeroUsize,
103 NonZeroIsize,
104 );