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]
34macro_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]
76macro_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)]
119macro_rules! assert_eq_size_val {
120 ($x:expr, $($xs:expr),+ $(,)?) => {
121 assert_eq_size_ptr!(&$x, $(&$xs),+);
122 }
123}
124