std_detect/detect/macros.rs
1/// Forward a literal to the relevant `__is_feature_detected` function.
2#[macro_export]
3#[allow_internal_unstable(stdarch_internal)]
4#[unstable(feature = "stdarch_internal", issue = "none")]
5macro_rules! detect_feature {
6 ($feature:tt, $feature_lit:tt) => {
7 $crate::detect_feature!($feature, $feature_lit : $feature_lit)
8 };
9 ($feature:tt, $feature_lit:tt : $($target_feature_lit:tt),*) => {
10 // Emit `true` if enabled at compile time
11 $(cfg!(target_feature = $target_feature_lit) ||)*
12 $crate::detect::__is_feature_detected::$feature()
13 };
14 ($feature:tt, $feature_lit:tt, without cfg check: true) => {
15 $crate::detect::__is_feature_detected::$feature()
16 };
17}
18
19/// Verify that all features are known by `cfg!`.
20#[allow(unused_macros, reason = "it's used in the features! macro below")]
21macro_rules! check_cfg_feature {
22 ($feature:tt, $feature_lit:tt) => {
23 check_cfg_feature!($feature, $feature_lit : $feature_lit)
24 };
25 ($feature:tt, $feature_lit:tt : $($target_feature_lit:tt),*) => {
26 $(cfg!(target_feature = $target_feature_lit);)*
27 };
28 ($feature:tt, $feature_lit:tt, without cfg check: $feature_cfg_check:literal) => {
29 #[allow(unexpected_cfgs, reason = $feature_lit)]
30 { cfg!(target_feature = $feature_lit) }
31 };
32}
33
34/// Create the `is_*_feature_detected` macro for an architecture.
35// Make sure any additions to this macro are tested in
36// `tests/ui/std/is_arch_feature_detected.AARCH64.stderr`.
37#[allow(unused)]
38macro_rules! features {
39 (
40 // Target or target family name, for use in diagnostic messages
41 @TARGET: $target:ident;
42 // Cfg for which this macro should be allowed
43 @CFG: $cfg:meta;
44 // Name like `is_*_feature_detected`
45 @MACRO_NAME: $macro_name:ident;
46 // Docs and stability attributes
47 @MACRO_ATTRS: $(#[$macro_attrs:meta])*
48 // Synonyms, with possible deprecation
49 $(@BIND_FEATURE_NAME: $bind_feature:tt; $feature_impl:tt; $(#[$deprecate_attr:meta];)?)*
50 // Features that exist but can't be detected at runtime, so emit an error.
51 $(@NO_RUNTIME_DETECTION: $nort_feature:tt; )*
52 // List of features
53 $(@FEATURE: #[$stability_attr:meta] $feature:ident: $feature_lit:tt;
54 // Skip verifying that the feature is known by `cfg!`, which also skips emitting `true`
55 // if the feature is enabled at compile time.
56 $(without cfg check: $feature_cfg_check:tt;)?
57 // If this feature is always enabled by some other feature, we can avoid the cost of
58 // checking them separately by instead only checking the root features.
59 $(implied by target_features: [$($target_feature_lit:tt),*];)?
60 // Doc comment for the feature.
61 $(#[$feature_comment:meta])*)*
62 ) => {
63 // The current arch's version actually does the feature detection.
64 #[macro_export]
65 $(#[$macro_attrs])*
66 #[allow_internal_unstable(stdarch_internal)]
67 #[cfg($cfg)]
68 #[doc(cfg($cfg))]
69 macro_rules! $macro_name {
70 // Emit all known features
71 $(
72 ($feature_lit) => {
73 $crate::detect_feature!(
74 $feature,
75 $feature_lit
76 $(, without cfg check: $feature_cfg_check)?
77 $(: $($target_feature_lit),*)?
78 )
79 };
80 )*
81 // Emit all aliases, with a deprecation notice if applicable
82 $(
83 ($bind_feature) => {
84 {
85 $(
86 #[$deprecate_attr] macro_rules! deprecated_feature { {} => {}; }
87 deprecated_feature! {};
88 )?
89 $crate::$macro_name!($feature_impl)
90 }
91 };
92 )*
93 // Emit an error for features that can't be detected at runtime
94 $(
95 ($nort_feature) => {
96 compile_error!(
97 concat!(
98 stringify!($nort_feature),
99 " feature cannot be detected at run-time"
100 )
101 )
102 };
103 )*
104 // Allow a trailing comma
105 ($t:tt,) => {
106 $crate::$macro_name!($t)
107 };
108 // Fallback, error for unknown target features
109 ($t:tt) => {
110 compile_error!(
111 concat!("unknown ", stringify!($target), " target feature: ", $t)
112 )
113 };
114 }
115
116 // All other arches still validate the features, but also
117 $(#[$macro_attrs])*
118 #[macro_export]
119 #[cfg(not($cfg))]
120 #[doc(cfg($cfg))]
121 macro_rules! $macro_name {
122 // All known features get an error
123 $(
124 ($feature_lit) => {
125 compile_error!(
126 concat!(
127 "This macro cannot be used on the current target. You can prevent\n\
128 it from being used in other architectures by guarding it behind\n\
129 a `cfg(", stringify!($cfg), ")`."
130 )
131 )
132 };
133 )*
134 // Forward deprecated features
135 $(
136 ($bind_feature) => { $crate::$macro_name!($feature_impl) };
137 )*
138 // Emit an error for features that can't be detected at runtime
139 $(
140 ($nort_feature) => {
141 compile_error!(
142 concat!(
143 stringify!($nort_feature),
144 " feature cannot be detected at run-time"
145 )
146 )
147 };
148 )*
149 // Allow a trailing comma
150 ($t:tt,) => {
151 $crate::$macro_name!($t);
152 };
153 // Fallback, error for unknown target features
154 ($t:tt) => {
155 compile_error!(
156 concat!("unknown ", stringify!($target), " target feature: ", $t)
157 )
158 };
159 }
160
161 #[deny(unexpected_cfgs)]
162 #[deny(unfulfilled_lint_expectations)]
163 const _: () = {
164 $(
165 check_cfg_feature!(
166 $feature,
167 $feature_lit
168 $(, without cfg check: $feature_cfg_check)?
169 $(: $($target_feature_lit),*)?)
170 ;
171 )*
172 };
173
174 /// Each variant denotes a position in a bitset for a particular feature.
175 ///
176 /// PLEASE: do not use this, it is an implementation detail subject
177 /// to change.
178 #[doc(hidden)]
179 #[allow(non_camel_case_types)]
180 #[derive(Copy, Clone)]
181 #[repr(u8)]
182 #[unstable(feature = "stdarch_internal", issue = "none")]
183 #[cfg($cfg)]
184 pub(crate) enum Feature {
185 $(
186 $(#[$feature_comment])*
187 $feature,
188 )*
189 }
190
191 #[cfg($cfg)]
192 impl Feature {
193 pub(crate) const ALL: &[Feature] = &[
194 $(Feature::$feature,)*
195 ];
196
197 pub(crate) fn to_str(self) -> &'static str {
198 match self {
199 $(Feature::$feature => $feature_lit,)*
200 }
201 }
202
203 #[cfg(feature = "std_detect_env_override")]
204 pub(crate) fn from_str(s: &str) -> Result<Feature, ()> {
205 match s {
206 $($feature_lit => Ok(Feature::$feature),)*
207 _ => Err(())
208 }
209 }
210 }
211
212 /// Each function performs run-time feature detection for a single
213 /// feature. This allow us to use stability attributes on a per feature
214 /// basis.
215 ///
216 /// PLEASE: do not use this, it is an implementation detail subject
217 /// to change.
218 #[doc(hidden)]
219 #[cfg($cfg)]
220 pub mod __is_feature_detected {
221 $(
222
223 /// PLEASE: do not use this, it is an implementation detail
224 /// subject to change.
225 #[inline]
226 #[doc(hidden)]
227 #[$stability_attr]
228 pub fn $feature() -> bool {
229 $crate::detect::check_for($crate::detect::Feature::$feature)
230 }
231 )*
232 }
233 };
234}