| 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 |  | 
|---|