1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/// Asserts that the type has the given fields.
///
/// # Examples
///
/// One common use case is when types have fields defined multiple times as a
/// result of `#[cfg]`. This can be an issue when exposing a public API.
///
#[cfg_attr(feature = "nightly", doc = "```ignore")]
#[cfg_attr(not(feature = "nightly"), doc = "```")]
/// # #[macro_use] extern crate static_assertions;
/// pub struct Ty {
///     #[cfg(windows)]
///     pub val1: u8,
///     #[cfg(not(windows))]
///     pub val1: usize,
///
///     #[cfg(unix)]
///     pub val2: u32,
///     #[cfg(not(unix))]
///     pub val2: usize,
/// }
///
/// // Requires a unique label in module scope
/// assert_fields!(windows; Ty, val1);
///
/// fn main() {
///     // Always have `val2` regardless of OS
///     assert_fields!(Ty, val2);
/// }
/// ```
///
/// The [labeling limitation](index.html#limitations) is not necessary if
/// compiling on nightly Rust with the `nightly` feature enabled:
///
#[cfg_attr(feature = "nightly", doc = "```")]
#[cfg_attr(not(feature = "nightly"), doc = "```ignore")]
/// #![feature(underscore_const_names)]
/// # #[macro_use] extern crate static_assertions;
///
/// use std::ops::Range;
///
/// assert_fields!(Range<u32>, start, end);
/// ```
///
/// Range does not have a field named `middle`:
///
/// ```compile_fail
/// # #[macro_use] extern crate static_assertions;
/// # fn main() {
/// # use std::ops::Range;
/// assert_fields!(Range<u32>, middle);
/// # }
/// ```
#[macro_export]
macro_rules! assert_fields {
    ($($xs:tt)+) => { _assert_fields!($($xs)+); };
}

#[doc(hidden)]
#[cfg(feature = "nightly")]
#[macro_export]
macro_rules! _assert_fields {
    ($t:path, $($f:ident),+) => {
        #[allow(unknown_lints, unneeded_field_pattern)]
        const _: fn() -> () = || {
            $(let $t { $f: _, .. };)+
        };
    };
}

#[doc(hidden)]
#[cfg(not(feature = "nightly"))]
#[macro_export]
macro_rules! _assert_fields {
    ($t:path, $($f:ident),+) => {
        #[allow(unknown_lints, unneeded_field_pattern)]
        { $(let $t { $f: _, .. };)+ }
    };
    ($label:ident; $($xs:tt)+) => {
        #[allow(dead_code, non_snake_case)]
        fn $label() { assert_fields!($($xs)+); }
    };
}