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