| use crate::boxed::Box; |
| |
| #[rustc_specialization_trait] |
| pub(super) unsafe trait IsZero { |
| /// Whether this value is zero |
| fn is_zero(&self) -> bool; |
| } |
| |
| macro_rules! impl_is_zero { |
| ($t:ty, $is_zero:expr) => { |
| unsafe impl IsZero for $t { |
| #[inline] |
| fn is_zero(&self) -> bool { |
| $is_zero(*self) |
| } |
| } |
| }; |
| } |
| |
| impl_is_zero!(i16, |x| x == 0); |
| impl_is_zero!(i32, |x| x == 0); |
| impl_is_zero!(i64, |x| x == 0); |
| impl_is_zero!(i128, |x| x == 0); |
| impl_is_zero!(isize, |x| x == 0); |
| |
| impl_is_zero!(u16, |x| x == 0); |
| impl_is_zero!(u32, |x| x == 0); |
| impl_is_zero!(u64, |x| x == 0); |
| impl_is_zero!(u128, |x| x == 0); |
| impl_is_zero!(usize, |x| x == 0); |
| |
| impl_is_zero!(bool, |x| x == false); |
| impl_is_zero!(char, |x| x == '\0'); |
| |
| impl_is_zero!(f32, |x: f32| x.to_bits() == 0); |
| impl_is_zero!(f64, |x: f64| x.to_bits() == 0); |
| |
| unsafe impl<T> IsZero for *const T { |
| #[inline] |
| fn is_zero(&self) -> bool { |
| (*self).is_null() |
| } |
| } |
| |
| unsafe impl<T> IsZero for *mut T { |
| #[inline] |
| fn is_zero(&self) -> bool { |
| (*self).is_null() |
| } |
| } |
| |
| // `Option<&T>` and `Option<Box<T>>` are guaranteed to represent `None` as null. |
| // For fat pointers, the bytes that would be the pointer metadata in the `Some` |
| // variant are padding in the `None` variant, so ignoring them and |
| // zero-initializing instead is ok. |
| // `Option<&mut T>` never implements `Clone`, so there's no need for an impl of |
| // `SpecFromElem`. |
| |
| unsafe impl<T: ?Sized> IsZero for Option<&T> { |
| #[inline] |
| fn is_zero(&self) -> bool { |
| self.is_none() |
| } |
| } |
| |
| unsafe impl<T: ?Sized> IsZero for Option<Box<T>> { |
| #[inline] |
| fn is_zero(&self) -> bool { |
| self.is_none() |
| } |
| } |