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] 53macro_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