     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71

    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()
        }
    }