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
#![no_std]
#[macro_export]
macro_rules! const_zero {
($type_:ty) => {{
const TYPE_SIZE: usize = core::mem::size_of::<$type_>();
union TypeAsBytes {
bytes: [u8; TYPE_SIZE],
inner: core::mem::ManuallyDrop<$type_>,
};
const ZERO: TypeAsBytes = TypeAsBytes {
bytes: [0; TYPE_SIZE],
};
core::mem::ManuallyDrop::<$type_>::into_inner(ZERO.inner)
}};
}
#[cfg(test)]
mod tests {
use core::num::NonZeroU8;
use core::num::Wrapping;
#[test]
fn multiple() {
const ZERO_1: i32 = unsafe { const_zero!(i32) };
const ZERO_2: i32 = unsafe { const_zero!(i32) };
const ZERO_3: i64 = unsafe { const_zero!(i64) };
assert_eq!(ZERO_1, 0);
assert_eq!(ZERO_2, 0);
assert_eq!(ZERO_3, 0);
}
#[test]
fn zeroed_int() {
macro_rules! test_int {
($type_:ty, $zero:expr) => {{
const ZERO: $type_ = unsafe { const_zero!($type_) };
assert_eq!(ZERO, $zero);
}};
}
test_int!(i8, 0);
test_int!(i16, 0);
test_int!(i32, 0);
test_int!(i64, 0);
test_int!(i128, 0);
test_int!(isize, 0);
test_int!(Wrapping<i8>, Wrapping(0));
test_int!(Wrapping<i16>, Wrapping(0));
test_int!(Wrapping<i32>, Wrapping(0));
test_int!(Wrapping<i64>, Wrapping(0));
test_int!(Wrapping<i128>, Wrapping(0));
test_int!(Wrapping<isize>, Wrapping(0));
test_int!(u8, 0);
test_int!(u16, 0);
test_int!(u32, 0);
test_int!(u64, 0);
test_int!(u128, 0);
test_int!(usize, 0);
test_int!(Wrapping<u8>, Wrapping(0));
test_int!(Wrapping<u16>, Wrapping(0));
test_int!(Wrapping<u32>, Wrapping(0));
test_int!(Wrapping<u64>, Wrapping(0));
test_int!(Wrapping<u128>, Wrapping(0));
test_int!(Wrapping<usize>, Wrapping(0));
test_int!(f32, 0.);
test_int!(f64, 0.);
}
#[test]
fn zeroed_ptr() {
const NULL: *const () = unsafe { const_zero!(*const ()) };
assert_eq!(NULL, core::ptr::null());
const NULL_MUT: *mut () = unsafe { const_zero!(*mut ()) };
assert_eq!(NULL_MUT, core::ptr::null_mut());
}
#[test]
fn zeroed_option() {
const NONE: Option<NonZeroU8> = unsafe { const_zero!(Option<NonZeroU8>) };
assert_eq!(NONE, None);
}
#[test]
fn drop_type() {
#[derive(Clone, Debug)]
struct Droppable {
inner: (),
}
impl Drop for Droppable {
fn drop(&mut self) {
}
}
#[allow(unused)]
const DROPPABLE: Droppable = unsafe { const_zero!(Droppable) };
}
#[test]
fn zeroed_unit() {
const UNIT: () = unsafe { const_zero!(()) };
assert_eq!((), UNIT);
}
}