• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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