]>
Commit | Line | Data |
---|---|---|
e1599b0c XL |
1 | //! Built-in attributes and `cfg` flag gating. |
2 | ||
e1599b0c | 3 | use AttributeGate::*; |
dfeec247 | 4 | use AttributeType::*; |
e1599b0c | 5 | |
60c5eb7d | 6 | use crate::{Features, Stability}; |
e1599b0c | 7 | |
dfeec247 XL |
8 | use rustc_data_structures::fx::FxHashMap; |
9 | use rustc_span::symbol::{sym, Symbol}; | |
e1599b0c | 10 | |
1b1a35ee XL |
11 | use std::lazy::SyncLazy; |
12 | ||
e1599b0c XL |
13 | type GateFn = fn(&Features) -> bool; |
14 | ||
15 | macro_rules! cfg_fn { | |
16 | ($field: ident) => { | |
dfeec247 XL |
17 | (|features| features.$field) as GateFn |
18 | }; | |
e1599b0c XL |
19 | } |
20 | ||
60c5eb7d XL |
21 | pub type GatedCfg = (Symbol, Symbol, GateFn); |
22 | ||
e1599b0c | 23 | /// `cfg(...)`'s that are feature gated. |
60c5eb7d | 24 | const GATED_CFGS: &[GatedCfg] = &[ |
e1599b0c XL |
25 | // (name in cfg, feature, function to check if the feature is enabled) |
26 | (sym::target_thread_local, sym::cfg_target_thread_local, cfg_fn!(cfg_target_thread_local)), | |
27 | (sym::target_has_atomic, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)), | |
e74abb32 | 28 | (sym::target_has_atomic_load_store, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)), |
1b1a35ee XL |
29 | ( |
30 | sym::target_has_atomic_equal_alignment, | |
31 | sym::cfg_target_has_atomic, | |
32 | cfg_fn!(cfg_target_has_atomic), | |
33 | ), | |
60c5eb7d | 34 | (sym::sanitize, sym::cfg_sanitize, cfg_fn!(cfg_sanitize)), |
f9f354fc | 35 | (sym::version, sym::cfg_version, cfg_fn!(cfg_version)), |
29967ef6 | 36 | (sym::panic, sym::cfg_panic, cfg_fn!(cfg_panic)), |
e1599b0c XL |
37 | ]; |
38 | ||
60c5eb7d XL |
39 | /// Find a gated cfg determined by the `pred`icate which is given the cfg's name. |
40 | pub fn find_gated_cfg(pred: impl Fn(Symbol) -> bool) -> Option<&'static GatedCfg> { | |
41 | GATED_CFGS.iter().find(|(cfg_sym, ..)| pred(*cfg_sym)) | |
e1599b0c XL |
42 | } |
43 | ||
44 | // If you change this, please modify `src/doc/unstable-book` as well. You must | |
45 | // move that documentation into the relevant place in the other docs, and | |
46 | // remove the chapter on the flag. | |
47 | ||
48 | #[derive(Copy, Clone, PartialEq, Debug)] | |
49 | pub enum AttributeType { | |
50 | /// Normal, builtin attribute that is consumed | |
51 | /// by the compiler before the unused_attribute check | |
52 | Normal, | |
53 | ||
54 | /// Builtin attribute that may not be consumed by the compiler | |
55 | /// before the unused_attribute check. These attributes | |
56 | /// will be ignored by the unused_attribute lint | |
f035d41b | 57 | AssumedUsed, |
e1599b0c XL |
58 | |
59 | /// Builtin attribute that is only allowed at the crate level | |
60 | CrateLevel, | |
61 | } | |
62 | ||
63 | #[derive(Clone, Copy)] | |
64 | pub enum AttributeGate { | |
65 | /// Is gated by a given feature gate, reason | |
66 | /// and function to check if enabled | |
67 | Gated(Stability, Symbol, &'static str, fn(&Features) -> bool), | |
68 | ||
69 | /// Ungated attribute, can be used on all release channels | |
70 | Ungated, | |
71 | } | |
72 | ||
73 | // fn() is not Debug | |
74 | impl std::fmt::Debug for AttributeGate { | |
75 | fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | |
76 | match *self { | |
dfeec247 XL |
77 | Self::Gated(ref stab, name, expl, _) => { |
78 | write!(fmt, "Gated({:?}, {}, {})", stab, name, expl) | |
79 | } | |
80 | Self::Ungated => write!(fmt, "Ungated"), | |
e1599b0c XL |
81 | } |
82 | } | |
83 | } | |
84 | ||
85 | impl AttributeGate { | |
86 | fn is_deprecated(&self) -> bool { | |
29967ef6 | 87 | matches!(*self, Self::Gated(Stability::Deprecated(_, _), ..)) |
e1599b0c XL |
88 | } |
89 | } | |
90 | ||
60c5eb7d XL |
91 | /// A template that the attribute input must match. |
92 | /// Only top-level shape (`#[attr]` vs `#[attr(...)]` vs `#[attr = ...]`) is considered now. | |
ba9703b0 | 93 | #[derive(Clone, Copy, Default)] |
60c5eb7d XL |
94 | pub struct AttributeTemplate { |
95 | pub word: bool, | |
96 | pub list: Option<&'static str>, | |
97 | pub name_value_str: Option<&'static str>, | |
98 | } | |
99 | ||
e1599b0c XL |
100 | /// A convenience macro for constructing attribute templates. |
101 | /// E.g., `template!(Word, List: "description")` means that the attribute | |
102 | /// supports forms `#[attr]` and `#[attr(description)]`. | |
103 | macro_rules! template { | |
104 | (Word) => { template!(@ true, None, None) }; | |
105 | (List: $descr: expr) => { template!(@ false, Some($descr), None) }; | |
106 | (NameValueStr: $descr: expr) => { template!(@ false, None, Some($descr)) }; | |
107 | (Word, List: $descr: expr) => { template!(@ true, Some($descr), None) }; | |
108 | (Word, NameValueStr: $descr: expr) => { template!(@ true, None, Some($descr)) }; | |
109 | (List: $descr1: expr, NameValueStr: $descr2: expr) => { | |
110 | template!(@ false, Some($descr1), Some($descr2)) | |
111 | }; | |
112 | (Word, List: $descr1: expr, NameValueStr: $descr2: expr) => { | |
113 | template!(@ true, Some($descr1), Some($descr2)) | |
114 | }; | |
115 | (@ $word: expr, $list: expr, $name_value_str: expr) => { AttributeTemplate { | |
116 | word: $word, list: $list, name_value_str: $name_value_str | |
117 | } }; | |
118 | } | |
119 | ||
120 | macro_rules! ungated { | |
121 | ($attr:ident, $typ:expr, $tpl:expr $(,)?) => { | |
122 | (sym::$attr, $typ, $tpl, Ungated) | |
123 | }; | |
124 | } | |
125 | ||
126 | macro_rules! gated { | |
127 | ($attr:ident, $typ:expr, $tpl:expr, $gate:ident, $msg:expr $(,)?) => { | |
128 | (sym::$attr, $typ, $tpl, Gated(Stability::Unstable, sym::$gate, $msg, cfg_fn!($gate))) | |
129 | }; | |
130 | ($attr:ident, $typ:expr, $tpl:expr, $msg:expr $(,)?) => { | |
131 | (sym::$attr, $typ, $tpl, Gated(Stability::Unstable, sym::$attr, $msg, cfg_fn!($attr))) | |
132 | }; | |
133 | } | |
134 | ||
135 | macro_rules! rustc_attr { | |
136 | (TEST, $attr:ident, $typ:expr, $tpl:expr $(,)?) => { | |
137 | rustc_attr!( | |
dfeec247 XL |
138 | $attr, |
139 | $typ, | |
140 | $tpl, | |
141 | concat!( | |
142 | "the `#[", | |
143 | stringify!($attr), | |
144 | "]` attribute is just used for rustc unit tests \ | |
e1599b0c XL |
145 | and will never be stable", |
146 | ), | |
147 | ) | |
148 | }; | |
149 | ($attr:ident, $typ:expr, $tpl:expr, $msg:expr $(,)?) => { | |
dfeec247 XL |
150 | ( |
151 | sym::$attr, | |
152 | $typ, | |
153 | $tpl, | |
154 | Gated(Stability::Unstable, sym::rustc_attrs, $msg, cfg_fn!(rustc_attrs)), | |
155 | ) | |
e1599b0c XL |
156 | }; |
157 | } | |
158 | ||
159 | macro_rules! experimental { | |
160 | ($attr:ident) => { | |
161 | concat!("the `#[", stringify!($attr), "]` attribute is an experimental feature") | |
dfeec247 | 162 | }; |
e1599b0c XL |
163 | } |
164 | ||
165 | const IMPL_DETAIL: &str = "internal implementation detail"; | |
60c5eb7d | 166 | const INTERNAL_UNSTABLE: &str = "this is an internal attribute that will never be stable"; |
e1599b0c XL |
167 | |
168 | pub type BuiltinAttribute = (Symbol, AttributeType, AttributeTemplate, AttributeGate); | |
169 | ||
170 | /// Attributes that have a special meaning to rustc or rustdoc. | |
dfeec247 | 171 | #[rustfmt::skip] |
e1599b0c XL |
172 | pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ |
173 | // ========================================================================== | |
174 | // Stable attributes: | |
175 | // ========================================================================== | |
176 | ||
74b04a01 | 177 | // Conditional compilation: |
e1599b0c XL |
178 | ungated!(cfg, Normal, template!(List: "predicate")), |
179 | ungated!(cfg_attr, Normal, template!(List: "predicate, attr1, attr2, ...")), | |
180 | ||
181 | // Testing: | |
182 | ungated!(ignore, Normal, template!(Word, NameValueStr: "reason")), | |
183 | ungated!( | |
184 | should_panic, Normal, | |
185 | template!(Word, List: r#"expected = "reason"#, NameValueStr: "reason"), | |
186 | ), | |
187 | // FIXME(Centril): This can be used on stable but shouldn't. | |
188 | ungated!(reexport_test_harness_main, Normal, template!(NameValueStr: "name")), | |
189 | ||
190 | // Macros: | |
e1599b0c XL |
191 | ungated!(automatically_derived, Normal, template!(Word)), |
192 | // FIXME(#14407) | |
193 | ungated!(macro_use, Normal, template!(Word, List: "name1, name2, ...")), | |
194 | ungated!(macro_escape, Normal, template!(Word)), // Deprecated synonym for `macro_use`. | |
195 | ungated!(macro_export, Normal, template!(Word, List: "local_inner_macros")), | |
196 | ungated!(proc_macro, Normal, template!(Word)), | |
197 | ungated!( | |
198 | proc_macro_derive, Normal, | |
199 | template!(List: "TraitName, /*opt*/ attributes(name1, name2, ...)"), | |
200 | ), | |
201 | ungated!(proc_macro_attribute, Normal, template!(Word)), | |
202 | ||
203 | // Lints: | |
204 | ungated!(warn, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)), | |
205 | ungated!(allow, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)), | |
206 | ungated!(forbid, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)), | |
207 | ungated!(deny, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#)), | |
f035d41b | 208 | ungated!(must_use, AssumedUsed, template!(Word, NameValueStr: "reason")), |
e1599b0c XL |
209 | // FIXME(#14407) |
210 | ungated!( | |
211 | deprecated, Normal, | |
212 | template!( | |
213 | Word, | |
214 | List: r#"/*opt*/ since = "version", /*opt*/ note = "reason""#, | |
215 | NameValueStr: "reason" | |
216 | ), | |
217 | ), | |
218 | ||
219 | // Crate properties: | |
220 | ungated!(crate_name, CrateLevel, template!(NameValueStr: "name")), | |
221 | ungated!(crate_type, CrateLevel, template!(NameValueStr: "bin|lib|...")), | |
222 | ungated!(crate_id, CrateLevel, template!(NameValueStr: "ignored")), | |
223 | ||
224 | // ABI, linking, symbols, and FFI | |
225 | ungated!( | |
f035d41b | 226 | link, AssumedUsed, |
ba9703b0 | 227 | template!(List: r#"name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...""#), |
e1599b0c | 228 | ), |
f035d41b | 229 | ungated!(link_name, AssumedUsed, template!(NameValueStr: "name")), |
e1599b0c | 230 | ungated!(no_link, Normal, template!(Word)), |
60c5eb7d | 231 | ungated!(repr, Normal, template!(List: "C")), |
f035d41b XL |
232 | ungated!(export_name, AssumedUsed, template!(NameValueStr: "name")), |
233 | ungated!(link_section, AssumedUsed, template!(NameValueStr: "name")), | |
234 | ungated!(no_mangle, AssumedUsed, template!(Word)), | |
235 | ungated!(used, AssumedUsed, template!(Word)), | |
e1599b0c XL |
236 | |
237 | // Limits: | |
238 | ungated!(recursion_limit, CrateLevel, template!(NameValueStr: "N")), | |
239 | ungated!(type_length_limit, CrateLevel, template!(NameValueStr: "N")), | |
74b04a01 XL |
240 | gated!( |
241 | const_eval_limit, CrateLevel, template!(NameValueStr: "N"), const_eval_limit, | |
242 | experimental!(const_eval_limit) | |
243 | ), | |
e1599b0c XL |
244 | |
245 | // Entry point: | |
246 | ungated!(main, Normal, template!(Word)), | |
247 | ungated!(start, Normal, template!(Word)), | |
248 | ungated!(no_start, CrateLevel, template!(Word)), | |
249 | ungated!(no_main, CrateLevel, template!(Word)), | |
250 | ||
251 | // Modules, prelude, and resolution: | |
252 | ungated!(path, Normal, template!(NameValueStr: "file")), | |
253 | ungated!(no_std, CrateLevel, template!(Word)), | |
254 | ungated!(no_implicit_prelude, Normal, template!(Word)), | |
f035d41b | 255 | ungated!(non_exhaustive, AssumedUsed, template!(Word)), |
e1599b0c XL |
256 | |
257 | // Runtime | |
f035d41b | 258 | ungated!(windows_subsystem, AssumedUsed, template!(NameValueStr: "windows|console")), |
e1599b0c XL |
259 | ungated!(panic_handler, Normal, template!(Word)), // RFC 2070 |
260 | ||
261 | // Code generation: | |
f035d41b XL |
262 | ungated!(inline, AssumedUsed, template!(Word, List: "always|never")), |
263 | ungated!(cold, AssumedUsed, template!(Word)), | |
264 | ungated!(no_builtins, AssumedUsed, template!(Word)), | |
265 | ungated!(target_feature, AssumedUsed, template!(List: r#"enable = "name""#)), | |
266 | ungated!(track_caller, AssumedUsed, template!(Word)), | |
74b04a01 | 267 | gated!( |
f035d41b | 268 | no_sanitize, AssumedUsed, |
74b04a01 XL |
269 | template!(List: "address, memory, thread"), |
270 | experimental!(no_sanitize) | |
271 | ), | |
e1599b0c | 272 | |
f035d41b XL |
273 | // FIXME: #14408 assume docs are used since rustdoc looks at them. |
274 | ungated!(doc, AssumedUsed, template!(List: "hidden|inline|...", NameValueStr: "string")), | |
e1599b0c XL |
275 | |
276 | // ========================================================================== | |
277 | // Unstable attributes: | |
278 | // ========================================================================== | |
279 | ||
280 | // Linking: | |
f035d41b | 281 | gated!(naked, AssumedUsed, template!(Word), naked_functions, experimental!(naked)), |
e1599b0c XL |
282 | gated!( |
283 | link_args, Normal, template!(NameValueStr: "args"), | |
284 | "the `link_args` attribute is experimental and not portable across platforms, \ | |
285 | it is recommended to use `#[link(name = \"foo\")] instead", | |
286 | ), | |
e74abb32 | 287 | gated!( |
f035d41b | 288 | link_ordinal, AssumedUsed, template!(List: "ordinal"), raw_dylib, |
e74abb32 XL |
289 | experimental!(link_ordinal) |
290 | ), | |
e1599b0c XL |
291 | |
292 | // Plugins: | |
e74abb32 XL |
293 | ( |
294 | sym::plugin_registrar, Normal, template!(Word), | |
295 | Gated( | |
296 | Stability::Deprecated( | |
297 | "https://github.com/rust-lang/rust/pull/64675", | |
298 | Some("may be removed in a future compiler version"), | |
299 | ), | |
300 | sym::plugin_registrar, | |
301 | "compiler plugins are deprecated", | |
302 | cfg_fn!(plugin_registrar) | |
303 | ) | |
304 | ), | |
305 | ( | |
60c5eb7d | 306 | sym::plugin, CrateLevel, template!(List: "name"), |
e74abb32 XL |
307 | Gated( |
308 | Stability::Deprecated( | |
309 | "https://github.com/rust-lang/rust/pull/64675", | |
310 | Some("may be removed in a future compiler version"), | |
311 | ), | |
312 | sym::plugin, | |
313 | "compiler plugins are deprecated", | |
314 | cfg_fn!(plugin) | |
315 | ) | |
e1599b0c XL |
316 | ), |
317 | ||
318 | // Testing: | |
319 | gated!(allow_fail, Normal, template!(Word), experimental!(allow_fail)), | |
320 | gated!( | |
321 | test_runner, CrateLevel, template!(List: "path"), custom_test_frameworks, | |
322 | "custom test frameworks are an unstable feature", | |
323 | ), | |
e1599b0c XL |
324 | // RFC #1268 |
325 | gated!(marker, Normal, template!(Word), marker_trait_attr, experimental!(marker)), | |
326 | gated!( | |
f035d41b | 327 | thread_local, AssumedUsed, template!(Word), |
e1599b0c XL |
328 | "`#[thread_local]` is an experimental feature, and does not currently handle destructors", |
329 | ), | |
330 | gated!(no_core, CrateLevel, template!(Word), experimental!(no_core)), | |
331 | // RFC 2412 | |
332 | gated!( | |
f035d41b | 333 | optimize, AssumedUsed, template!(List: "size|speed"), optimize_attribute, |
e1599b0c XL |
334 | experimental!(optimize), |
335 | ), | |
29967ef6 XL |
336 | // RFC 2867 |
337 | gated!(instruction_set, AssumedUsed, template!(List: "set"), isa_attribute, experimental!(instruction_set)), | |
e1599b0c | 338 | |
f035d41b XL |
339 | gated!(ffi_returns_twice, AssumedUsed, template!(Word), experimental!(ffi_returns_twice)), |
340 | gated!(ffi_pure, AssumedUsed, template!(Word), experimental!(ffi_pure)), | |
341 | gated!(ffi_const, AssumedUsed, template!(Word), experimental!(ffi_const)), | |
60c5eb7d XL |
342 | gated!( |
343 | register_attr, CrateLevel, template!(List: "attr1, attr2, ..."), | |
344 | experimental!(register_attr), | |
345 | ), | |
346 | gated!( | |
347 | register_tool, CrateLevel, template!(List: "tool1, tool2, ..."), | |
348 | experimental!(register_tool), | |
349 | ), | |
e1599b0c | 350 | |
1b1a35ee XL |
351 | gated!(cmse_nonsecure_entry, AssumedUsed, template!(Word), experimental!(cmse_nonsecure_entry)), |
352 | ||
e1599b0c XL |
353 | // ========================================================================== |
354 | // Internal attributes: Stability, deprecation, and unsafe: | |
355 | // ========================================================================== | |
356 | ||
357 | ungated!(feature, CrateLevel, template!(List: "name1, name1, ...")), | |
358 | // FIXME(#14407) -- only looked at on-demand so we can't | |
359 | // guarantee they'll have already been checked. | |
360 | ungated!( | |
f035d41b | 361 | rustc_deprecated, AssumedUsed, |
e1599b0c XL |
362 | template!(List: r#"since = "version", reason = "...""#) |
363 | ), | |
364 | // FIXME(#14407) | |
f035d41b | 365 | ungated!(stable, AssumedUsed, template!(List: r#"feature = "name", since = "version""#)), |
e1599b0c XL |
366 | // FIXME(#14407) |
367 | ungated!( | |
f035d41b | 368 | unstable, AssumedUsed, |
e1599b0c XL |
369 | template!(List: r#"feature = "name", reason = "...", issue = "N""#), |
370 | ), | |
60c5eb7d | 371 | // FIXME(#14407) |
f035d41b | 372 | ungated!(rustc_const_unstable, AssumedUsed, template!(List: r#"feature = "name""#)), |
60c5eb7d | 373 | // FIXME(#14407) |
f035d41b | 374 | ungated!(rustc_const_stable, AssumedUsed, template!(List: r#"feature = "name""#)), |
e1599b0c | 375 | gated!( |
f035d41b | 376 | allow_internal_unstable, AssumedUsed, template!(Word, List: "feat1, feat2, ..."), |
60c5eb7d | 377 | "allow_internal_unstable side-steps feature gating and stability checks", |
e1599b0c | 378 | ), |
29967ef6 XL |
379 | gated!( |
380 | rustc_allow_const_fn_unstable, AssumedUsed, template!(Word, List: "feat1, feat2, ..."), | |
381 | "rustc_allow_const_fn_unstable side-steps feature gating and stability checks" | |
382 | ), | |
e1599b0c | 383 | gated!( |
60c5eb7d XL |
384 | allow_internal_unsafe, Normal, template!(Word), |
385 | "allow_internal_unsafe side-steps the unsafe_code lint", | |
e1599b0c | 386 | ), |
e1599b0c XL |
387 | |
388 | // ========================================================================== | |
389 | // Internal attributes: Type system related: | |
390 | // ========================================================================== | |
391 | ||
f035d41b | 392 | gated!(fundamental, AssumedUsed, template!(Word), experimental!(fundamental)), |
e1599b0c XL |
393 | gated!( |
394 | may_dangle, Normal, template!(Word), dropck_eyepatch, | |
395 | "`may_dangle` has unstable semantics and may be removed in the future", | |
396 | ), | |
397 | ||
398 | // ========================================================================== | |
399 | // Internal attributes: Runtime related: | |
400 | // ========================================================================== | |
401 | ||
f035d41b XL |
402 | rustc_attr!(rustc_allocator, AssumedUsed, template!(Word), IMPL_DETAIL), |
403 | rustc_attr!(rustc_allocator_nounwind, AssumedUsed, template!(Word), IMPL_DETAIL), | |
e1599b0c XL |
404 | gated!(alloc_error_handler, Normal, template!(Word), experimental!(alloc_error_handler)), |
405 | gated!( | |
f035d41b | 406 | default_lib_allocator, AssumedUsed, template!(Word), allocator_internals, |
e1599b0c XL |
407 | experimental!(default_lib_allocator), |
408 | ), | |
409 | gated!( | |
410 | needs_allocator, Normal, template!(Word), allocator_internals, | |
411 | experimental!(needs_allocator), | |
412 | ), | |
f035d41b XL |
413 | gated!(panic_runtime, AssumedUsed, template!(Word), experimental!(panic_runtime)), |
414 | gated!(needs_panic_runtime, AssumedUsed, template!(Word), experimental!(needs_panic_runtime)), | |
e1599b0c | 415 | gated!( |
f035d41b | 416 | unwind, AssumedUsed, template!(List: "allowed|aborts"), unwind_attributes, |
e1599b0c XL |
417 | experimental!(unwind), |
418 | ), | |
419 | gated!( | |
f035d41b | 420 | compiler_builtins, AssumedUsed, template!(Word), |
e1599b0c XL |
421 | "the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate \ |
422 | which contains compiler-rt intrinsics and will never be stable", | |
423 | ), | |
e1599b0c | 424 | gated!( |
f035d41b | 425 | profiler_runtime, AssumedUsed, template!(Word), |
e1599b0c XL |
426 | "the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate \ |
427 | which contains the profiler runtime and will never be stable", | |
428 | ), | |
429 | ||
430 | // ========================================================================== | |
431 | // Internal attributes, Linkage: | |
432 | // ========================================================================== | |
433 | ||
434 | gated!( | |
f035d41b | 435 | linkage, AssumedUsed, template!(NameValueStr: "external|internal|..."), |
e1599b0c XL |
436 | "the `linkage` attribute is experimental and not portable across platforms", |
437 | ), | |
f035d41b | 438 | rustc_attr!(rustc_std_internal_symbol, AssumedUsed, template!(Word), INTERNAL_UNSTABLE), |
e1599b0c XL |
439 | |
440 | // ========================================================================== | |
441 | // Internal attributes, Macro related: | |
442 | // ========================================================================== | |
443 | ||
5869c6ff | 444 | rustc_attr!(rustc_builtin_macro, AssumedUsed, template!(Word, NameValueStr: "name"), IMPL_DETAIL), |
60c5eb7d | 445 | rustc_attr!(rustc_proc_macro_decls, Normal, template!(Word), INTERNAL_UNSTABLE), |
e1599b0c | 446 | rustc_attr!( |
f035d41b | 447 | rustc_macro_transparency, AssumedUsed, |
e1599b0c XL |
448 | template!(NameValueStr: "transparent|semitransparent|opaque"), |
449 | "used internally for testing macro hygiene", | |
450 | ), | |
451 | ||
452 | // ========================================================================== | |
453 | // Internal attributes, Diagnostics related: | |
454 | // ========================================================================== | |
455 | ||
60c5eb7d | 456 | rustc_attr!( |
f035d41b | 457 | rustc_on_unimplemented, AssumedUsed, |
e1599b0c XL |
458 | template!( |
459 | List: r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#, | |
460 | NameValueStr: "message" | |
461 | ), | |
60c5eb7d | 462 | INTERNAL_UNSTABLE |
e1599b0c | 463 | ), |
f035d41b XL |
464 | // Enumerates "identity-like" conversion methods to suggest on type mismatch. |
465 | rustc_attr!(rustc_conversion_suggestion, AssumedUsed, template!(Word), INTERNAL_UNSTABLE), | |
e1599b0c XL |
466 | |
467 | // ========================================================================== | |
468 | // Internal attributes, Const related: | |
469 | // ========================================================================== | |
470 | ||
f035d41b | 471 | rustc_attr!(rustc_promotable, AssumedUsed, template!(Word), IMPL_DETAIL), |
f035d41b | 472 | rustc_attr!(rustc_args_required_const, AssumedUsed, template!(List: "N"), INTERNAL_UNSTABLE), |
6a06907d | 473 | rustc_attr!(rustc_legacy_const_generics, AssumedUsed, template!(List: "N"), INTERNAL_UNSTABLE), |
e1599b0c XL |
474 | |
475 | // ========================================================================== | |
476 | // Internal attributes, Layout related: | |
477 | // ========================================================================== | |
478 | ||
479 | rustc_attr!( | |
f035d41b | 480 | rustc_layout_scalar_valid_range_start, AssumedUsed, template!(List: "value"), |
e1599b0c XL |
481 | "the `#[rustc_layout_scalar_valid_range_start]` attribute is just used to enable \ |
482 | niche optimizations in libcore and will never be stable", | |
483 | ), | |
484 | rustc_attr!( | |
f035d41b | 485 | rustc_layout_scalar_valid_range_end, AssumedUsed, template!(List: "value"), |
e1599b0c XL |
486 | "the `#[rustc_layout_scalar_valid_range_end]` attribute is just used to enable \ |
487 | niche optimizations in libcore and will never be stable", | |
488 | ), | |
489 | rustc_attr!( | |
f035d41b | 490 | rustc_nonnull_optimization_guaranteed, AssumedUsed, template!(Word), |
e1599b0c XL |
491 | "the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to enable \ |
492 | niche optimizations in libcore and will never be stable", | |
493 | ), | |
494 | ||
495 | // ========================================================================== | |
496 | // Internal attributes, Misc: | |
497 | // ========================================================================== | |
e1599b0c XL |
498 | gated!( |
499 | lang, Normal, template!(NameValueStr: "name"), lang_items, | |
500 | "language items are subject to change", | |
501 | ), | |
502 | ( | |
503 | sym::rustc_diagnostic_item, | |
504 | Normal, | |
505 | template!(NameValueStr: "name"), | |
506 | Gated( | |
507 | Stability::Unstable, | |
508 | sym::rustc_attrs, | |
509 | "diagnostic items compiler internal support for linting", | |
510 | cfg_fn!(rustc_attrs), | |
511 | ), | |
512 | ), | |
e1599b0c XL |
513 | gated!( |
514 | // Used in resolve: | |
f035d41b | 515 | prelude_import, AssumedUsed, template!(Word), |
e1599b0c XL |
516 | "`#[prelude_import]` is for use by rustc only", |
517 | ), | |
518 | gated!( | |
519 | rustc_paren_sugar, Normal, template!(Word), unboxed_closures, | |
520 | "unboxed_closures are still evolving", | |
521 | ), | |
522 | rustc_attr!( | |
f035d41b | 523 | rustc_inherit_overflow_checks, AssumedUsed, template!(Word), |
e1599b0c XL |
524 | "the `#[rustc_inherit_overflow_checks]` attribute is just used to control \ |
525 | overflow checking behavior of several libcore functions that are inlined \ | |
526 | across crates and will never be stable", | |
527 | ), | |
e74abb32 XL |
528 | rustc_attr!(rustc_reservation_impl, Normal, template!(NameValueStr: "reservation message"), |
529 | "the `#[rustc_reservation_impl]` attribute is internally used \ | |
530 | for reserving for `for<T> From<!> for T` impl" | |
531 | ), | |
e1599b0c XL |
532 | rustc_attr!( |
533 | rustc_test_marker, Normal, template!(Word), | |
534 | "the `#[rustc_test_marker]` attribute is used internally to track tests", | |
535 | ), | |
ba9703b0 XL |
536 | rustc_attr!( |
537 | rustc_unsafe_specialization_marker, Normal, template!(Word), | |
538 | "the `#[rustc_unsafe_specialization_marker]` attribute is used to check specializations" | |
539 | ), | |
540 | rustc_attr!( | |
541 | rustc_specialization_trait, Normal, template!(Word), | |
542 | "the `#[rustc_specialization_trait]` attribute is used to check specializations" | |
543 | ), | |
e1599b0c XL |
544 | |
545 | // ========================================================================== | |
546 | // Internal attributes, Testing: | |
547 | // ========================================================================== | |
548 | ||
549 | rustc_attr!(TEST, rustc_outlives, Normal, template!(Word)), | |
fc512014 | 550 | rustc_attr!(TEST, rustc_capture_analysis, Normal, template!(Word)), |
e1599b0c XL |
551 | rustc_attr!(TEST, rustc_variance, Normal, template!(Word)), |
552 | rustc_attr!(TEST, rustc_layout, Normal, template!(List: "field1, field2, ...")), | |
553 | rustc_attr!(TEST, rustc_regions, Normal, template!(Word)), | |
60c5eb7d | 554 | rustc_attr!( |
f035d41b | 555 | TEST, rustc_error, AssumedUsed, |
60c5eb7d XL |
556 | template!(Word, List: "delay_span_bug_from_inside_query") |
557 | ), | |
f035d41b XL |
558 | rustc_attr!(TEST, rustc_dump_user_substs, AssumedUsed, template!(Word)), |
559 | rustc_attr!(TEST, rustc_if_this_changed, AssumedUsed, template!(Word, List: "DepNode")), | |
560 | rustc_attr!(TEST, rustc_then_this_would_need, AssumedUsed, template!(List: "DepNode")), | |
e1599b0c | 561 | rustc_attr!( |
f035d41b | 562 | TEST, rustc_dirty, AssumedUsed, |
e1599b0c XL |
563 | template!(List: r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#), |
564 | ), | |
565 | rustc_attr!( | |
f035d41b | 566 | TEST, rustc_clean, AssumedUsed, |
e1599b0c XL |
567 | template!(List: r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#), |
568 | ), | |
569 | rustc_attr!( | |
f035d41b | 570 | TEST, rustc_partition_reused, AssumedUsed, |
e1599b0c XL |
571 | template!(List: r#"cfg = "...", module = "...""#), |
572 | ), | |
573 | rustc_attr!( | |
f035d41b | 574 | TEST, rustc_partition_codegened, AssumedUsed, |
e1599b0c XL |
575 | template!(List: r#"cfg = "...", module = "...""#), |
576 | ), | |
577 | rustc_attr!( | |
f035d41b | 578 | TEST, rustc_expected_cgu_reuse, AssumedUsed, |
e1599b0c XL |
579 | template!(List: r#"cfg = "...", module = "...", kind = "...""#), |
580 | ), | |
f035d41b XL |
581 | rustc_attr!(TEST, rustc_synthetic, AssumedUsed, template!(Word)), |
582 | rustc_attr!(TEST, rustc_symbol_name, AssumedUsed, template!(Word)), | |
3dfed10e | 583 | rustc_attr!(TEST, rustc_polymorphize_error, AssumedUsed, template!(Word)), |
f035d41b XL |
584 | rustc_attr!(TEST, rustc_def_path, AssumedUsed, template!(Word)), |
585 | rustc_attr!(TEST, rustc_mir, AssumedUsed, template!(List: "arg1, arg2, ...")), | |
586 | rustc_attr!(TEST, rustc_dump_program_clauses, AssumedUsed, template!(Word)), | |
587 | rustc_attr!(TEST, rustc_dump_env_program_clauses, AssumedUsed, template!(Word)), | |
588 | rustc_attr!(TEST, rustc_object_lifetime_default, AssumedUsed, template!(Word)), | |
e1599b0c XL |
589 | rustc_attr!(TEST, rustc_dummy, Normal, template!(Word /* doesn't matter*/)), |
590 | gated!( | |
f035d41b | 591 | omit_gdb_pretty_printer_section, AssumedUsed, template!(Word), |
e1599b0c XL |
592 | "the `#[omit_gdb_pretty_printer_section]` attribute is just used for the Rust test suite", |
593 | ), | |
594 | ]; | |
595 | ||
596 | pub fn deprecated_attributes() -> Vec<&'static BuiltinAttribute> { | |
597 | BUILTIN_ATTRIBUTES.iter().filter(|(.., gate)| gate.is_deprecated()).collect() | |
598 | } | |
599 | ||
60c5eb7d | 600 | pub fn is_builtin_attr_name(name: Symbol) -> bool { |
e1599b0c XL |
601 | BUILTIN_ATTRIBUTE_MAP.get(&name).is_some() |
602 | } | |
603 | ||
29967ef6 | 604 | pub static BUILTIN_ATTRIBUTE_MAP: SyncLazy<FxHashMap<Symbol, &BuiltinAttribute>> = |
1b1a35ee | 605 | SyncLazy::new(|| { |
e1599b0c XL |
606 | let mut map = FxHashMap::default(); |
607 | for attr in BUILTIN_ATTRIBUTES.iter() { | |
608 | if map.insert(attr.0, attr).is_some() { | |
609 | panic!("duplicate builtin attribute `{}`", attr.0); | |
610 | } | |
611 | } | |
612 | map | |
1b1a35ee | 613 | }); |