1 /// Asserts that the type has the given fields. 2 /// 3 /// # Examples 4 /// 5 /// One common use case is when types have fields defined multiple times as a 6 /// result of `#[cfg]`. This can be an issue when exposing a public API. 7 /// 8 /// ``` 9 /// # #[macro_use] extern crate static_assertions; 10 /// pub struct Ty { 11 /// #[cfg(windows)] 12 /// pub val1: u8, 13 /// #[cfg(not(windows))] 14 /// pub val1: usize, 15 /// 16 /// #[cfg(unix)] 17 /// pub val2: u32, 18 /// #[cfg(not(unix))] 19 /// pub val2: usize, 20 /// } 21 /// 22 /// // Always have `val2` regardless of OS 23 /// assert_fields!(Ty: val2); 24 /// ``` 25 /// 26 /// This macro even works with `enum` variants: 27 /// 28 /// ``` 29 /// # #[macro_use] extern crate static_assertions; fn main() {} 30 /// enum Data { 31 /// Val { 32 /// id: i32, 33 /// name: String, 34 /// bytes: [u8; 128], 35 /// }, 36 /// Ptr(*const u8), 37 /// } 38 /// 39 /// assert_fields!(Data::Val: id, bytes); 40 /// ``` 41 /// 42 /// The following example fails to compile because [`Range`] does not have a field named `middle`: 43 /// 44 /// ```compile_fail 45 /// # #[macro_use] extern crate static_assertions; fn main() {} 46 /// use std::ops::Range; 47 /// 48 /// assert_fields!(Range<u32>: middle); 49 /// ``` 50 /// 51 /// [`Range`]: https://doc.rust-lang.org/std/ops/struct.Range.html 52 #[macro_export] 53 macro_rules! assert_fields { 54 ($t:ident::$v:ident: $($f:ident),+) => { 55 #[allow(unknown_lints, unneeded_field_pattern)] 56 const _: fn() = || { 57 #[allow(dead_code, unreachable_patterns)] 58 fn assert(value: $t) { 59 match value { 60 $($t::$v { $f: _, .. } => {},)+ 61 _ => {} 62 } 63 } 64 }; 65 }; 66 ($t:path: $($f:ident),+) => { 67 #[allow(unknown_lints, unneeded_field_pattern)] 68 const _: fn() = || { 69 $(let $t { $f: _, .. };)+ 70 }; 71 }; 72 } 73