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