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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
use core::num::{Saturating, Wrapping};

use crate::boxed::Box;

#[rustc_specialization_trait]
pub(super) unsafe trait IsZero {
    /// 此值的表示形式是全零,还是可以用全零表示。
    ///
    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!(i8, |x| x == 0); // i8 的数组和元组需要实现。
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!(u8, |x| x == 0); // u8 的数组和元组需要实现。
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()
    }
}

unsafe impl<T: IsZero, const N: usize> IsZero for [T; N] {
    #[inline]
    fn is_zero(&self) -> bool {
        // 因为这是作为运行时检查生成的,所以如果数组很长,就不太值得这么做。
        // 这里的阈值在很大程度上是任意的,但由于截至 2022 年 7 月 1 日 LLVM 无法对 `vec![[1; 32]; n]` 中的检查进行 const 折叠而被选中
        //
        // See https://github.com/rust-lang/rust/pull/97581#issuecomment-1166628022
        // 如果您有更好的证据,请随意调整。
        //

        N <= 16 && self.iter().all(IsZero::is_zero)
    }
}

// 这是递归的宏。
macro_rules! impl_for_tuples {
    // Stopper
    () => {
        // 空元组没有用,因为它是 ZST。
    };
    ($first_arg:ident $(,$rest:ident)*) => {
        unsafe impl <$first_arg: IsZero, $($rest: IsZero,)*> IsZero for ($first_arg, $($rest,)*){
            #[inline]
            fn is_zero(&self) -> bool{
                // 解构元组到 N 引用 Rust 允许通过局部变量名隐藏泛型参数。
                //
                #[allow(non_snake_case)]
                let ($first_arg, $($rest,)*) = self;

                $first_arg.is_zero()
                    $( && $rest.is_zero() )*
            }
        }

        impl_for_tuples!($($rest),*);
    }
}

impl_for_tuples!(A, B, C, D, E, F, G, H);

// `Option<&T>` 和 `Option<Box<T>>` 保证将 `None` 表示为空。
// 对于胖指针,将在 `Some` 变体中作为指针元数据的字节填充在 `None` 变体中,因此可以忽略它们,而可以将其初始化为零。
//
// `Option<&mut T>` 从不实现 `Clone`,因此不需要 `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()
    }
}

// `Option<num::NonZeroU32>` 和类似的具有表示保证它们与相应的 `u32` 类型具有相同的大小,并保证 `NonZeroU32` 和 `Option<num::NonZeroU32>` 之间的转换有效。
//
// 虽然正式的文档将 `None` 转换为 UB,但我们是标准库,因此我们可以进行额外的推断,我们知道唯一可用来表示 `None` 的利基是一个全是零的。
//
//
//

macro_rules! impl_is_zero_option_of_nonzero {
    ($($t:ident,)+) => {$(
        unsafe impl IsZero for Option<core::num::$t> {
            #[inline]
            fn is_zero(&self) -> bool {
                self.is_none()
            }
        }
    )+};
}

impl_is_zero_option_of_nonzero!(
    NonZeroU8,
    NonZeroU16,
    NonZeroU32,
    NonZeroU64,
    NonZeroU128,
    NonZeroI8,
    NonZeroI16,
    NonZeroI32,
    NonZeroI64,
    NonZeroI128,
    NonZeroUsize,
    NonZeroIsize,
);

macro_rules! impl_is_zero_option_of_num {
    ($($t:ty,)+) => {$(
        unsafe impl IsZero for Option<$t> {
            #[inline]
            fn is_zero(&self) -> bool {
                const {
                    let none: Self = unsafe { core::mem::MaybeUninit::zeroed().assume_init() };
                    assert!(none.is_none());
                }
                self.is_none()
            }
        }
    )+};
}

impl_is_zero_option_of_num!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, usize, isize,);

unsafe impl<T: IsZero> IsZero for Wrapping<T> {
    #[inline]
    fn is_zero(&self) -> bool {
        self.0.is_zero()
    }
}

unsafe impl<T: IsZero> IsZero for Saturating<T> {
    #[inline]
    fn is_zero(&self) -> bool {
        self.0.is_zero()
    }
}

macro_rules! impl_for_optional_bool {
    ($($t:ty,)+) => {$(
        unsafe impl IsZero for $t {
            #[inline]
            fn is_zero(&self) -> bool {
                // SAFETY: 这*不是*一个稳定的布局保证,但在 `core` 内部,我们可以依赖当前的 rustc 行为,即 bool 选项将是一个没有填充的字节,只要它们的嵌套深度小于 254。
                //
                //
                //
                let raw: u8 = unsafe { core::mem::transmute(*self) };
                raw == 0
            }
        }
    )+};
}
impl_for_optional_bool! {
    Option<bool>,
    Option<Option<bool>>,
    Option<Option<Option<bool>>>,
    // 可以走得更远,但不值得元数据开销
}