/// Asserts that types are equal in size. /// /// When performing operations such as pointer casts or dealing with [`usize`] /// versus [`u64`] versus [`u32`], the size of your types matter. That is where /// this macro comes into play. /// /// # Alternatives /// /// There also exists [`assert_eq_size_val`](macro.assert_eq_size_val.html) and /// [`assert_eq_size_ptr`](macro.assert_eq_size_ptr.html). Instead of specifying /// types to compare, values' sizes can be directly compared against each other. /// /// # Examples /// /// These three types, despite being very different, all have the same size: /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_eq_size!([u8; 4], (u16, u16), u32); /// ``` /// /// The following example fails to compile because `u32` has 4 times the size of /// `u8`: /// /// ```compile_fail /// # #[macro_use] extern crate static_assertions; fn main() {} /// assert_eq_size!(u32, u8); /// ``` /// /// [`usize`]: https://doc.rust-lang.org/std/primitive.usize.html /// [`u64`]: https://doc.rust-lang.org/std/primitive.u64.html /// [`u32`]: https://doc.rust-lang.org/std/primitive.u32.html #[macro_export] macro_rules! assert_eq_size { ($x:ty, $($xs:ty),+ $(,)?) => { const _: fn() = || { $(let _ = $crate::_core::mem::transmute::<$x, $xs>;)+ }; }; } /// Asserts that values pointed to are equal in size. /// /// # Examples /// /// This especially is useful for when coercing pointers between different types /// and ensuring the underlying values are the same size. /// /// ``` /// # #[macro_use] extern crate static_assertions; fn main() {} /// fn operation(x: &(u32, u32), y: &[u16; 4]) { /// assert_eq_size_ptr!(x, y); /// // ... /// } /// ``` /// /// The following example fails to compile because byte arrays of different /// lengths have different sizes: /// /// ```compile_fail /// # #[macro_use] extern crate static_assertions; /// # fn main() { /// static BYTES: &[u8; 4] = &[ /// /* ... */ /// # 0; 4 /// ]; /// /// static TABLE: &[u8; 16] = &[ /// /* ... */ /// # 0; 16 /// ]; /// /// assert_eq_size_ptr!(BYTES, TABLE); /// ``` #[macro_export] macro_rules! assert_eq_size_ptr { ($x:expr, $($xs:expr),+ $(,)?) => { #[allow(unknown_lints, unsafe_code, forget_copy, useless_transmute)] let _ = || unsafe { use $crate::_core::{mem, ptr}; let mut copy = ptr::read($x); $(ptr::write(&mut copy, mem::transmute(ptr::read($xs)));)+ mem::forget(copy); }; } } /// Asserts that values are equal in size. /// /// This macro doesn't consume its arguments and thus works for /// non-[`Clone`]able values. /// /// # Examples /// /// ``` /// # #[macro_use] extern crate static_assertions; /// # fn main() { /// struct Byte(u8); /// /// let x = 10u8; /// let y = Byte(42); // Works for non-cloneable types /// /// assert_eq_size_val!(x, y); /// assert_eq_size_val!(x, y, 0u8); /// # } /// ``` /// /// Even though both values are 0, they are of types with different sizes: /// /// ```compile_fail /// # #[macro_use] extern crate static_assertions; /// # fn main() { /// assert_eq_size_val!(0u8, 0u32); /// # } /// ``` /// /// [`Clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html #[macro_export(local_inner_macros)] macro_rules! assert_eq_size_val { ($x:expr, $($xs:expr),+ $(,)?) => { assert_eq_size_ptr!(&$x, $(&$xs),+); } }