1#![no_std]
2
3#[doc(hidden)]
4pub use core;
5
6#[macro_export]
45macro_rules! const_zero {
46 ($type_:ty) => {{
47 const TYPE_SIZE: $crate::core::primitive::usize = $crate::core::mem::size_of::<$type_>();
48 union TypeAsBytes {
49 bytes: [$crate::core::primitive::u8; TYPE_SIZE],
50 inner: $crate::core::mem::ManuallyDrop<$type_>,
51 }
52 const ZERO: TypeAsBytes = TypeAsBytes {
53 bytes: [0; TYPE_SIZE],
54 };
55 $crate::core::mem::ManuallyDrop::<$type_>::into_inner(ZERO.inner)
56 }};
57}
58
59#[cfg(test)]
60mod tests {
61 use core::num::NonZeroU8;
62 use core::num::Wrapping;
63
64 #[test]
66 fn multiple() {
67 const ZERO_1: i32 = unsafe { const_zero!(i32) };
68 const ZERO_2: i32 = unsafe { const_zero!(i32) };
69 const ZERO_3: i64 = unsafe { const_zero!(i64) };
70 assert_eq!(ZERO_1, 0);
71 assert_eq!(ZERO_2, 0);
72 assert_eq!(ZERO_3, 0);
73 }
74
75 #[test]
77 fn zeroed_int() {
78 macro_rules! test_int {
79 ($type_:ty, $zero:expr) => {{
80 const ZERO: $type_ = unsafe { const_zero!($type_) };
81 assert_eq!(ZERO, $zero);
82 }};
83 }
84 test_int!(i8, 0);
85 test_int!(i16, 0);
86 test_int!(i32, 0);
87 test_int!(i64, 0);
88 test_int!(i128, 0);
89 test_int!(isize, 0);
90 test_int!(Wrapping<i8>, Wrapping(0));
91 test_int!(Wrapping<i16>, Wrapping(0));
92 test_int!(Wrapping<i32>, Wrapping(0));
93 test_int!(Wrapping<i64>, Wrapping(0));
94 test_int!(Wrapping<i128>, Wrapping(0));
95 test_int!(Wrapping<isize>, Wrapping(0));
96
97 test_int!(u8, 0);
98 test_int!(u16, 0);
99 test_int!(u32, 0);
100 test_int!(u64, 0);
101 test_int!(u128, 0);
102 test_int!(usize, 0);
103 test_int!(Wrapping<u8>, Wrapping(0));
104 test_int!(Wrapping<u16>, Wrapping(0));
105 test_int!(Wrapping<u32>, Wrapping(0));
106 test_int!(Wrapping<u64>, Wrapping(0));
107 test_int!(Wrapping<u128>, Wrapping(0));
108 test_int!(Wrapping<usize>, Wrapping(0));
109
110 test_int!(f32, 0.);
111 test_int!(f64, 0.);
112 }
113
114 #[test]
115 fn zeroed_ptr() {
116 const NULL: *const () = unsafe { const_zero!(*const ()) };
117 assert_eq!(NULL, core::ptr::null());
118 const NULL_MUT: *mut () = unsafe { const_zero!(*mut ()) };
119 assert_eq!(NULL_MUT, core::ptr::null_mut());
120 }
121
122 #[test]
124 fn zeroed_option() {
125 const NONE: Option<NonZeroU8> = unsafe { const_zero!(Option<NonZeroU8>) };
126 assert_eq!(NONE, None);
127 }
128
129 #[test]
131 fn drop_type() {
132 #[derive(Clone, Debug)]
133 struct Droppable {}
134 impl Drop for Droppable {
135 fn drop(&mut self) {
136 }
138 }
139 #[allow(unused)]
140 const DROPPABLE: Droppable = unsafe { const_zero!(Droppable) };
141 }
142
143 #[test]
144 fn zeroed_unit() {
145 const UNIT: () = unsafe { const_zero!(()) };
146 assert_eq!((), UNIT);
147 }
148}
149
150#[cfg(test)]
151mod test_no_implicit_prelude {
152 #![no_implicit_prelude]
153
154 #[test]
155 fn zeroed_unit() {
156 const UNIT: () = unsafe { const_zero!(()) };
157 ::core::assert_eq!((), UNIT);
158 }
159}