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