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