1 | /// Asserts that types are equal in size. |
2 | /// |
3 | /// When performing operations such as pointer casts or dealing with [`usize`] |
4 | /// versus [`u64`] versus [`u32`], the size of your types matter. That is where |
5 | /// this macro comes into play. |
6 | /// |
7 | /// # Alternatives |
8 | /// |
9 | /// There also exists [`assert_eq_size_val`](macro.assert_eq_size_val.html) and |
10 | /// [`assert_eq_size_ptr`](macro.assert_eq_size_ptr.html). Instead of specifying |
11 | /// types to compare, values' sizes can be directly compared against each other. |
12 | /// |
13 | /// # Examples |
14 | /// |
15 | /// These three types, despite being very different, all have the same size: |
16 | /// |
17 | /// ``` |
18 | /// # #[macro_use ] extern crate static_assertions; fn main() {} |
19 | /// assert_eq_size!([u8; 4], (u16, u16), u32); |
20 | /// ``` |
21 | /// |
22 | /// The following example fails to compile because `u32` has 4 times the size of |
23 | /// `u8`: |
24 | /// |
25 | /// ```compile_fail |
26 | /// # #[macro_use ] extern crate static_assertions; fn main() {} |
27 | /// assert_eq_size!(u32, u8); |
28 | /// ``` |
29 | /// |
30 | /// [`usize`]: https://doc.rust-lang.org/std/primitive.usize.html |
31 | /// [`u64`]: https://doc.rust-lang.org/std/primitive.u64.html |
32 | /// [`u32`]: https://doc.rust-lang.org/std/primitive.u32.html |
33 | #[macro_export ] |
34 | macro_rules! assert_eq_size { |
35 | ($x:ty, $($xs:ty),+ $(,)?) => { |
36 | const _: fn() = || { |
37 | $(let _ = $crate::_core::mem::transmute::<$x, $xs>;)+ |
38 | }; |
39 | }; |
40 | } |
41 | |
42 | /// Asserts that values pointed to are equal in size. |
43 | /// |
44 | /// # Examples |
45 | /// |
46 | /// This especially is useful for when coercing pointers between different types |
47 | /// and ensuring the underlying values are the same size. |
48 | /// |
49 | /// ``` |
50 | /// # #[macro_use ] extern crate static_assertions; fn main() {} |
51 | /// fn operation(x: &(u32, u32), y: &[u16; 4]) { |
52 | /// assert_eq_size_ptr!(x, y); |
53 | /// // ... |
54 | /// } |
55 | /// ``` |
56 | /// |
57 | /// The following example fails to compile because byte arrays of different |
58 | /// lengths have different sizes: |
59 | /// |
60 | /// ```compile_fail |
61 | /// # #[macro_use ] extern crate static_assertions; |
62 | /// # fn main() { |
63 | /// static BYTES: &[u8; 4] = &[ |
64 | /// /* ... */ |
65 | /// # 0; 4 |
66 | /// ]; |
67 | /// |
68 | /// static TABLE: &[u8; 16] = &[ |
69 | /// /* ... */ |
70 | /// # 0; 16 |
71 | /// ]; |
72 | /// |
73 | /// assert_eq_size_ptr!(BYTES, TABLE); |
74 | /// ``` |
75 | #[macro_export ] |
76 | macro_rules! assert_eq_size_ptr { |
77 | ($x:expr, $($xs:expr),+ $(,)?) => { |
78 | #[allow(unknown_lints, unsafe_code, forget_copy, useless_transmute)] |
79 | let _ = || unsafe { |
80 | use $crate::_core::{mem, ptr}; |
81 | let mut copy = ptr::read($x); |
82 | $(ptr::write(&mut copy, mem::transmute(ptr::read($xs)));)+ |
83 | mem::forget(copy); |
84 | }; |
85 | } |
86 | } |
87 | |
88 | /// Asserts that values are equal in size. |
89 | /// |
90 | /// This macro doesn't consume its arguments and thus works for |
91 | /// non-[`Clone`]able values. |
92 | /// |
93 | /// # Examples |
94 | /// |
95 | /// ``` |
96 | /// # #[macro_use ] extern crate static_assertions; |
97 | /// # fn main() { |
98 | /// struct Byte(u8); |
99 | /// |
100 | /// let x = 10u8; |
101 | /// let y = Byte(42); // Works for non-cloneable types |
102 | /// |
103 | /// assert_eq_size_val!(x, y); |
104 | /// assert_eq_size_val!(x, y, 0u8); |
105 | /// # } |
106 | /// ``` |
107 | /// |
108 | /// Even though both values are 0, they are of types with different sizes: |
109 | /// |
110 | /// ```compile_fail |
111 | /// # #[macro_use ] extern crate static_assertions; |
112 | /// # fn main() { |
113 | /// assert_eq_size_val!(0u8, 0u32); |
114 | /// # } |
115 | /// ``` |
116 | /// |
117 | /// [`Clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html |
118 | #[macro_export (local_inner_macros)] |
119 | macro_rules! assert_eq_size_val { |
120 | ($x:expr, $($xs:expr),+ $(,)?) => { |
121 | assert_eq_size_ptr!(&$x, $(&$xs),+); |
122 | } |
123 | } |
124 | |