std_detect/detect/
macros.rs

1#[macro_export]
2#[allow_internal_unstable(stdarch_internal)]
3#[unstable(feature = "stdarch_internal", issue = "none")]
4macro_rules! detect_feature {
5    ($feature:tt, $feature_lit:tt) => {
6        $crate::detect_feature!($feature, $feature_lit : $feature_lit)
7    };
8    ($feature:tt, $feature_lit:tt : $($target_feature_lit:tt),*) => {
9        $(cfg!(target_feature = $target_feature_lit) ||)*
10            $crate::detect::__is_feature_detected::$feature()
11    };
12    ($feature:tt, $feature_lit:tt, without cfg check: true) => {
13        $crate::detect::__is_feature_detected::$feature()
14    };
15}
16
17#[allow(unused_macros, reason = "it's used in the features! macro below")]
18macro_rules! check_cfg_feature {
19    ($feature:tt, $feature_lit:tt) => {
20        check_cfg_feature!($feature, $feature_lit : $feature_lit)
21    };
22    ($feature:tt, $feature_lit:tt : $($target_feature_lit:tt),*) => {
23        $(cfg!(target_feature = $target_feature_lit);)*
24    };
25    ($feature:tt, $feature_lit:tt, without cfg check: $feature_cfg_check:literal) => {
26        #[allow(unexpected_cfgs, reason = $feature_lit)]
27        { cfg!(target_feature = $feature_lit) }
28    };
29}
30
31#[allow(unused)]
32macro_rules! features {
33    (
34      @TARGET: $target:ident;
35      @CFG: $cfg:meta;
36      @MACRO_NAME: $macro_name:ident;
37      @MACRO_ATTRS: $(#[$macro_attrs:meta])*
38      $(@BIND_FEATURE_NAME: $bind_feature:tt; $feature_impl:tt; $(#[$deprecate_attr:meta];)?)*
39      $(@NO_RUNTIME_DETECTION: $nort_feature:tt; )*
40      $(@FEATURE: #[$stability_attr:meta] $feature:ident: $feature_lit:tt;
41          $(without cfg check: $feature_cfg_check:tt;)?
42          $(implied by target_features: [$($target_feature_lit:tt),*];)?
43          $(#[$feature_comment:meta])*)*
44    ) => {
45        #[macro_export]
46        $(#[$macro_attrs])*
47        #[allow_internal_unstable(stdarch_internal)]
48        #[cfg($cfg)]
49        #[doc(cfg($cfg))]
50        macro_rules! $macro_name {
51            $(
52                ($feature_lit) => {
53                    $crate::detect_feature!($feature, $feature_lit $(, without cfg check: $feature_cfg_check)? $(: $($target_feature_lit),*)?)
54                };
55            )*
56            $(
57                ($bind_feature) => {
58                    {
59                        $(
60                            #[$deprecate_attr] macro_rules! deprecated_feature { {} => {}; }
61                            deprecated_feature! {};
62                        )?
63                        $crate::$macro_name!($feature_impl)
64                    }
65                };
66            )*
67            $(
68                ($nort_feature) => {
69                    compile_error!(
70                        concat!(
71                            stringify!($nort_feature),
72                            " feature cannot be detected at run-time"
73                        )
74                    )
75                };
76            )*
77            ($t:tt,) => {
78                    $crate::$macro_name!($t);
79            };
80            ($t:tt) => {
81                compile_error!(
82                    concat!(
83                        concat!("unknown ", stringify!($target)),
84                        concat!(" target feature: ", $t)
85                    )
86                )
87            };
88        }
89
90        $(#[$macro_attrs])*
91        #[macro_export]
92        #[cfg(not($cfg))]
93        #[doc(cfg($cfg))]
94        macro_rules! $macro_name {
95            $(
96                ($feature_lit) => {
97                    compile_error!(
98                        concat!(
99                            r#"This macro cannot be used on the current target.
100                            You can prevent it from being used in other architectures by
101                            guarding it behind a cfg("#,
102                            stringify!($cfg),
103                            ")."
104                        )
105                    )
106                };
107            )*
108            $(
109                ($bind_feature) => { $crate::$macro_name!($feature_impl) };
110            )*
111            $(
112                ($nort_feature) => {
113                    compile_error!(
114                        concat!(
115                            stringify!($nort_feature),
116                            " feature cannot be detected at run-time"
117                        )
118                    )
119                };
120            )*
121            ($t:tt,) => {
122                    $crate::$macro_name!($t);
123            };
124            ($t:tt) => {
125                compile_error!(
126                    concat!(
127                        concat!("unknown ", stringify!($target)),
128                        concat!(" target feature: ", $t)
129                    )
130                )
131            };
132        }
133
134        #[test]
135        #[deny(unexpected_cfgs)]
136        #[deny(unfulfilled_lint_expectations)]
137        fn unexpected_cfgs() {
138            $(
139                check_cfg_feature!($feature, $feature_lit $(, without cfg check: $feature_cfg_check)? $(: $($target_feature_lit),*)?);
140            )*
141        }
142
143        /// Each variant denotes a position in a bitset for a particular feature.
144        ///
145        /// PLEASE: do not use this, it is an implementation detail subject
146        /// to change.
147        #[doc(hidden)]
148        #[allow(non_camel_case_types)]
149        #[derive(Copy, Clone)]
150        #[repr(u8)]
151        #[unstable(feature = "stdarch_internal", issue = "none")]
152        #[cfg($cfg)]
153        pub(crate) enum Feature {
154            $(
155                $(#[$feature_comment])*
156                $feature,
157            )*
158
159            // Do not add variants after last:
160            _last
161        }
162
163        #[cfg($cfg)]
164        impl Feature {
165            pub(crate) fn to_str(self) -> &'static str {
166                match self {
167                    $(Feature::$feature => $feature_lit,)*
168                    Feature::_last => unreachable!(),
169                }
170            }
171        }
172
173        /// Each function performs run-time feature detection for a single
174        /// feature. This allow us to use stability attributes on a per feature
175        /// basis.
176        ///
177        /// PLEASE: do not use this, it is an implementation detail subject
178        /// to change.
179        #[doc(hidden)]
180        #[cfg($cfg)]
181        #[unstable(feature = "stdarch_internal", issue = "none")]
182        pub mod __is_feature_detected {
183            $(
184
185                /// PLEASE: do not use this, it is an implementation detail
186                /// subject to change.
187                #[inline]
188                #[doc(hidden)]
189                #[$stability_attr]
190                pub fn $feature() -> bool {
191                    $crate::detect::check_for($crate::detect::Feature::$feature)
192                }
193            )*
194        }
195    };
196}