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        #[deny(unexpected_cfgs)]
135        #[deny(unfulfilled_lint_expectations)]
136        const _: () = {
137            $(
138                check_cfg_feature!($feature, $feature_lit $(, without cfg check: $feature_cfg_check)? $(: $($target_feature_lit),*)?);
139            )*
140        };
141
142        /// Each variant denotes a position in a bitset for a particular feature.
143        ///
144        /// PLEASE: do not use this, it is an implementation detail subject
145        /// to change.
146        #[doc(hidden)]
147        #[allow(non_camel_case_types)]
148        #[derive(Copy, Clone)]
149        #[repr(u8)]
150        #[unstable(feature = "stdarch_internal", issue = "none")]
151        #[cfg($cfg)]
152        pub(crate) enum Feature {
153            $(
154                $(#[$feature_comment])*
155                $feature,
156            )*
157
158            // Do not add variants after last:
159            _last
160        }
161
162        #[cfg($cfg)]
163        impl Feature {
164            pub(crate) fn to_str(self) -> &'static str {
165                match self {
166                    $(Feature::$feature => $feature_lit,)*
167                    Feature::_last => unreachable!(),
168                }
169            }
170
171            #[cfg(feature = "std_detect_env_override")]
172            pub(crate) fn from_str(s: &str) -> Result<Feature, ()> {
173                match s {
174                    $($feature_lit => Ok(Feature::$feature),)*
175                    _ => Err(())
176                }
177            }
178        }
179
180        /// Each function performs run-time feature detection for a single
181        /// feature. This allow us to use stability attributes on a per feature
182        /// basis.
183        ///
184        /// PLEASE: do not use this, it is an implementation detail subject
185        /// to change.
186        #[doc(hidden)]
187        #[cfg($cfg)]
188        #[unstable(feature = "stdarch_internal", issue = "none")]
189        pub mod __is_feature_detected {
190            $(
191
192                /// PLEASE: do not use this, it is an implementation detail
193                /// subject to change.
194                #[inline]
195                #[doc(hidden)]
196                #[$stability_attr]
197                pub fn $feature() -> bool {
198                    $crate::detect::check_for($crate::detect::Feature::$feature)
199                }
200            )*
201        }
202    };
203}