• 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_size_eq_val`](macro.assert_size_eq_val.html) and
10 /// [`assert_size_eq_ptr`](macro.assert_size_eq_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_size_eq!([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_size_eq!(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_size_eq {
35     ($x:ty, $($xs:ty),+ $(,)?) => {
36         const _: fn() = || {
37             $(let _ = $crate::_core::mem::transmute::<$x, $xs>;)+
38         };
39     };
40 }
41 
42 /// Asserts that types are equal in alignment.
43 ///
44 /// This macro has been deprecated in favor of
45 /// [`assert_size_eq!`](macro.assert_size_eq.html).
46 #[deprecated(
47     since = "1.2.0",
48     note = "Please use the 'assert_size_eq' macro instead"
49 )]
50 #[macro_export(local_inner_macros)]
51 macro_rules! assert_eq_size {
52     ($($t:tt)*) => {
53         assert_size_eq!($($t)*);
54     };
55 }
56 
57 /// Asserts that values pointed to are equal in size.
58 ///
59 /// # Examples
60 ///
61 /// This especially is useful for when coercing pointers between different types
62 /// and ensuring the underlying values are the same size.
63 ///
64 /// ```
65 /// # #[macro_use] extern crate static_assertions; fn main() {}
66 /// fn operation(x: &(u32, u32), y: &[u16; 4]) {
67 ///     assert_size_eq_ptr!(x, y);
68 ///     // ...
69 /// }
70 /// ```
71 ///
72 /// The following example fails to compile because byte arrays of different
73 /// lengths have different sizes:
74 ///
75 /// ```compile_fail
76 /// # #[macro_use] extern crate static_assertions;
77 /// # fn main() {
78 /// static BYTES: &[u8; 4] = &[
79 ///     /* ... */
80 ///     # 0; 4
81 /// ];
82 ///
83 /// static TABLE: &[u8; 16] = &[
84 ///     /* ... */
85 ///     # 0; 16
86 /// ];
87 ///
88 /// assert_size_eq_ptr!(BYTES, TABLE);
89 /// ```
90 #[macro_export]
91 macro_rules! assert_size_eq_ptr {
92     ($x:expr, $($xs:expr),+ $(,)?) => {
93         #[allow(unknown_lints, unsafe_code, forget_copy, useless_transmute)]
94         let _ = || unsafe {
95             use $crate::_core::{mem, ptr};
96             let mut copy = ptr::read($x);
97             $(ptr::write(&mut copy, mem::transmute(ptr::read($xs)));)+
98             mem::forget(copy);
99         };
100     }
101 }
102 
103 /// Asserts that values pointed to are equal in size.
104 ///
105 /// This macro has been deprecated in favor of
106 /// [`assert_size_eq_ptr!`](macro.assert_size_eq_ptr.html).
107 #[deprecated(
108     since = "1.2.0",
109     note = "Please use the 'assert_size_eq_ptr' macro instead"
110 )]
111 #[macro_export(local_inner_macros)]
112 macro_rules! assert_eq_size_ptr {
113     ($($t:tt)*) => {
114         assert_size_eq_ptr!($($t)*);
115     };
116 }
117 
118 /// Asserts that values are equal in size.
119 ///
120 /// This macro doesn't consume its arguments and thus works for
121 /// non-[`Clone`]able values.
122 ///
123 /// # Examples
124 ///
125 /// ```
126 /// # #[macro_use] extern crate static_assertions;
127 /// # fn main() {
128 /// struct Byte(u8);
129 ///
130 /// let x = 10u8;
131 /// let y = Byte(42); // Works for non-cloneable types
132 ///
133 /// assert_size_eq_val!(x, y);
134 /// assert_size_eq_val!(x, y, 0u8);
135 /// # }
136 /// ```
137 ///
138 /// Even though both values are 0, they are of types with different sizes:
139 ///
140 /// ```compile_fail
141 /// # #[macro_use] extern crate static_assertions;
142 /// # fn main() {
143 /// assert_size_eq_val!(0u8, 0u32);
144 /// # }
145 /// ```
146 ///
147 /// [`Clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html
148 #[macro_export(local_inner_macros)]
149 macro_rules! assert_size_eq_val {
150     ($x:expr, $($xs:expr),+ $(,)?) => {
151         assert_size_eq_ptr!(&$x, $(&$xs),+);
152     }
153 }
154 
155 /// Asserts that values pointed to are equal in size.
156 ///
157 /// This macro has been deprecated in favor of
158 /// [`assert_size_eq_val!`](macro.assert_size_eq_val.html).
159 #[deprecated(
160     since = "1.2.0",
161     note = "Please use the 'assert_size_eq_val' macro instead"
162 )]
163 #[macro_export(local_inner_macros)]
164 macro_rules! assert_eq_size_val {
165     ($($t:tt)*) => {
166         assert_size_eq_val!($($t)*);
167     };
168 }
169