1use std::sync::LazyLock;
4
5use AttributeDuplicates::*;
6use AttributeGate::*;
7use AttributeType::*;
8use rustc_data_structures::fx::FxHashMap;
9use rustc_hir::attrs::EncodeCrossCrate;
10use rustc_span::edition::Edition;
11use rustc_span::{Symbol, sym};
12
13use crate::Features;
14
15type GateFn = fn(&Features) -> bool;
16
17pub type GatedCfg = (Symbol, Symbol, GateFn);
18
19const GATED_CFGS: &[GatedCfg] = &[
21 (sym::overflow_checks, sym::cfg_overflow_checks, Features::cfg_overflow_checks),
23 (sym::ub_checks, sym::cfg_ub_checks, Features::cfg_ub_checks),
24 (sym::contract_checks, sym::cfg_contract_checks, Features::cfg_contract_checks),
25 (sym::target_thread_local, sym::cfg_target_thread_local, Features::cfg_target_thread_local),
26 (
27 sym::target_has_atomic_equal_alignment,
28 sym::cfg_target_has_atomic_equal_alignment,
29 Features::cfg_target_has_atomic_equal_alignment,
30 ),
31 (
32 sym::target_has_atomic_load_store,
33 sym::cfg_target_has_atomic,
34 Features::cfg_target_has_atomic,
35 ),
36 (sym::sanitize, sym::cfg_sanitize, Features::cfg_sanitize),
37 (sym::version, sym::cfg_version, Features::cfg_version),
38 (sym::relocation_model, sym::cfg_relocation_model, Features::cfg_relocation_model),
39 (sym::sanitizer_cfi_generalize_pointers, sym::cfg_sanitizer_cfi, Features::cfg_sanitizer_cfi),
40 (sym::sanitizer_cfi_normalize_integers, sym::cfg_sanitizer_cfi, Features::cfg_sanitizer_cfi),
41 (sym::fmt_debug, sym::fmt_debug, Features::fmt_debug),
43 (sym::emscripten_wasm_eh, sym::cfg_emscripten_wasm_eh, Features::cfg_emscripten_wasm_eh),
44 (
45 sym::target_has_reliable_f16,
46 sym::cfg_target_has_reliable_f16_f128,
47 Features::cfg_target_has_reliable_f16_f128,
48 ),
49 (
50 sym::target_has_reliable_f16_math,
51 sym::cfg_target_has_reliable_f16_f128,
52 Features::cfg_target_has_reliable_f16_f128,
53 ),
54 (
55 sym::target_has_reliable_f128,
56 sym::cfg_target_has_reliable_f16_f128,
57 Features::cfg_target_has_reliable_f16_f128,
58 ),
59 (
60 sym::target_has_reliable_f128_math,
61 sym::cfg_target_has_reliable_f16_f128,
62 Features::cfg_target_has_reliable_f16_f128,
63 ),
64];
65
66pub fn find_gated_cfg(pred: impl Fn(Symbol) -> bool) -> Option<&'static GatedCfg> {
68 GATED_CFGS.iter().find(|(cfg_sym, ..)| pred(*cfg_sym))
69}
70
71#[derive(Copy, Clone, PartialEq, Debug)]
76pub enum AttributeType {
77 Normal,
80
81 CrateLevel,
83}
84
85#[derive(Copy, Clone, PartialEq, Debug)]
86pub enum AttributeSafety {
87 Normal,
89
90 Unsafe { unsafe_since: Option<Edition> },
96}
97
98#[derive(Clone, Debug, Copy)]
99pub enum AttributeGate {
100 Gated {
102 feature: Symbol,
104 message: &'static str,
106 check: fn(&Features) -> bool,
108 notes: &'static [&'static str],
110 },
111 Ungated,
113}
114
115#[derive(Clone, Copy, Default)]
119pub struct AttributeTemplate {
120 pub word: bool,
122 pub list: Option<&'static str>,
124 pub one_of: &'static [Symbol],
127 pub name_value_str: Option<&'static str>,
130}
131
132impl AttributeTemplate {
133 pub fn suggestions(&self, inner: bool, name: impl std::fmt::Display) -> Vec<String> {
134 let mut suggestions = vec![];
135 let inner = if inner { "!" } else { "" };
136 if self.word {
137 suggestions.push(format!("#{inner}[{name}]"));
138 }
139 if let Some(descr) = self.list {
140 suggestions.push(format!("#{inner}[{name}({descr})]"));
141 }
142 suggestions.extend(self.one_of.iter().map(|&word| format!("#{inner}[{name}({word})]")));
143 if let Some(descr) = self.name_value_str {
144 suggestions.push(format!("#{inner}[{name} = \"{descr}\"]"));
145 }
146 suggestions.sort();
147
148 suggestions
149 }
150}
151
152#[derive(Clone, Copy, Default)]
154pub enum AttributeDuplicates {
155 #[default]
162 DuplicatesOk,
163 WarnFollowing,
169 WarnFollowingWordOnly,
175 ErrorFollowing,
181 ErrorPreceding,
187 FutureWarnFollowing,
194 FutureWarnPreceding,
201}
202
203#[macro_export]
207macro_rules! template {
208 (Word) => { $crate::template!(@ true, None, &[], None) };
209 (List: $descr: expr) => { $crate::template!(@ false, Some($descr), &[], None) };
210 (OneOf: $one_of: expr) => { $crate::template!(@ false, None, $one_of, None) };
211 (NameValueStr: $descr: expr) => { $crate::template!(@ false, None, &[], Some($descr)) };
212 (Word, List: $descr: expr) => { $crate::template!(@ true, Some($descr), &[], None) };
213 (Word, NameValueStr: $descr: expr) => { $crate::template!(@ true, None, &[], Some($descr)) };
214 (List: $descr1: expr, NameValueStr: $descr2: expr) => {
215 $crate::template!(@ false, Some($descr1), &[], Some($descr2))
216 };
217 (Word, List: $descr1: expr, NameValueStr: $descr2: expr) => {
218 $crate::template!(@ true, Some($descr1), &[], Some($descr2))
219 };
220 (@ $word: expr, $list: expr, $one_of: expr, $name_value_str: expr) => { $crate::AttributeTemplate {
221 word: $word, list: $list, one_of: $one_of, name_value_str: $name_value_str
222 } };
223}
224
225macro_rules! ungated {
226 (unsafe($edition:ident) $attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr $(,)?) => {
227 BuiltinAttribute {
228 name: sym::$attr,
229 encode_cross_crate: $encode_cross_crate,
230 type_: $typ,
231 safety: AttributeSafety::Unsafe { unsafe_since: Some(Edition::$edition) },
232 template: $tpl,
233 gate: Ungated,
234 duplicates: $duplicates,
235 }
236 };
237 (unsafe $attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr $(,)?) => {
238 BuiltinAttribute {
239 name: sym::$attr,
240 encode_cross_crate: $encode_cross_crate,
241 type_: $typ,
242 safety: AttributeSafety::Unsafe { unsafe_since: None },
243 template: $tpl,
244 gate: Ungated,
245 duplicates: $duplicates,
246 }
247 };
248 ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr $(,)?) => {
249 BuiltinAttribute {
250 name: sym::$attr,
251 encode_cross_crate: $encode_cross_crate,
252 type_: $typ,
253 safety: AttributeSafety::Normal,
254 template: $tpl,
255 gate: Ungated,
256 duplicates: $duplicates,
257 }
258 };
259}
260
261macro_rules! gated {
262 (unsafe $attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr, $gate:ident, $message:expr $(,)?) => {
263 BuiltinAttribute {
264 name: sym::$attr,
265 encode_cross_crate: $encode_cross_crate,
266 type_: $typ,
267 safety: AttributeSafety::Unsafe { unsafe_since: None },
268 template: $tpl,
269 duplicates: $duplicates,
270 gate: Gated {
271 feature: sym::$gate,
272 message: $message,
273 check: Features::$gate,
274 notes: &[],
275 },
276 }
277 };
278 (unsafe $attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr, $message:expr $(,)?) => {
279 BuiltinAttribute {
280 name: sym::$attr,
281 encode_cross_crate: $encode_cross_crate,
282 type_: $typ,
283 safety: AttributeSafety::Unsafe { unsafe_since: None },
284 template: $tpl,
285 duplicates: $duplicates,
286 gate: Gated {
287 feature: sym::$attr,
288 message: $message,
289 check: Features::$attr,
290 notes: &[],
291 },
292 }
293 };
294 ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr, $gate:ident, $message:expr $(,)?) => {
295 BuiltinAttribute {
296 name: sym::$attr,
297 encode_cross_crate: $encode_cross_crate,
298 type_: $typ,
299 safety: AttributeSafety::Normal,
300 template: $tpl,
301 duplicates: $duplicates,
302 gate: Gated {
303 feature: sym::$gate,
304 message: $message,
305 check: Features::$gate,
306 notes: &[],
307 },
308 }
309 };
310 ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr, $message:expr $(,)?) => {
311 BuiltinAttribute {
312 name: sym::$attr,
313 encode_cross_crate: $encode_cross_crate,
314 type_: $typ,
315 safety: AttributeSafety::Normal,
316 template: $tpl,
317 duplicates: $duplicates,
318 gate: Gated {
319 feature: sym::$attr,
320 message: $message,
321 check: Features::$attr,
322 notes: &[],
323 },
324 }
325 };
326}
327
328macro_rules! rustc_attr {
329 (TEST, $attr:ident, $typ:expr, $tpl:expr, $duplicate:expr, $encode_cross_crate:expr $(,)?) => {
330 rustc_attr!(
331 $attr,
332 $typ,
333 $tpl,
334 $duplicate,
335 $encode_cross_crate,
336 concat!(
337 "the `#[",
338 stringify!($attr),
339 "]` attribute is used for rustc unit tests"
340 ),
341 )
342 };
343 ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr, $($notes:expr),* $(,)?) => {
344 BuiltinAttribute {
345 name: sym::$attr,
346 encode_cross_crate: $encode_cross_crate,
347 type_: $typ,
348 safety: AttributeSafety::Normal,
349 template: $tpl,
350 duplicates: $duplicates,
351 gate: Gated {
352 feature: sym::rustc_attrs,
353 message: "use of an internal attribute",
354 check: Features::rustc_attrs,
355 notes: &[
356 concat!("the `#[",
357 stringify!($attr),
358 "]` attribute is an internal implementation detail that will never be stable"),
359 $($notes),*
360 ]
361 },
362 }
363 };
364}
365
366macro_rules! experimental {
367 ($attr:ident) => {
368 concat!("the `#[", stringify!($attr), "]` attribute is an experimental feature")
369 };
370}
371
372pub struct BuiltinAttribute {
373 pub name: Symbol,
374 pub encode_cross_crate: EncodeCrossCrate,
379 pub type_: AttributeType,
380 pub safety: AttributeSafety,
381 pub template: AttributeTemplate,
382 pub duplicates: AttributeDuplicates,
383 pub gate: AttributeGate,
384}
385
386#[rustfmt::skip]
388pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
389 ungated!(cfg, Normal, template!(List: "predicate"), DuplicatesOk, EncodeCrossCrate::Yes),
395 ungated!(cfg_attr, Normal, template!(List: "predicate, attr1, attr2, ..."), DuplicatesOk, EncodeCrossCrate::Yes),
396
397 ungated!(
399 ignore, Normal, template!(Word, NameValueStr: "reason"), WarnFollowing,
400 EncodeCrossCrate::No,
401 ),
402 ungated!(
403 should_panic, Normal,
404 template!(Word, List: r#"expected = "reason""#, NameValueStr: "reason"), FutureWarnFollowing,
405 EncodeCrossCrate::No,
406 ),
407 ungated!(
409 reexport_test_harness_main, CrateLevel, template!(NameValueStr: "name"), ErrorFollowing,
410 EncodeCrossCrate::No,
411 ),
412
413 ungated!(automatically_derived, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes),
415 ungated!(
416 macro_use, Normal, template!(Word, List: "name1, name2, ..."), WarnFollowingWordOnly,
417 EncodeCrossCrate::No,
418 ),
419 ungated!(macro_escape, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No), ungated!(
421 macro_export, Normal, template!(Word, List: "local_inner_macros"),
422 WarnFollowing, EncodeCrossCrate::Yes
423 ),
424 ungated!(proc_macro, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::No),
425 ungated!(
426 proc_macro_derive, Normal, template!(List: "TraitName, /*opt*/ attributes(name1, name2, ...)"),
427 ErrorFollowing, EncodeCrossCrate::No,
428 ),
429 ungated!(proc_macro_attribute, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::No),
430
431 ungated!(
433 warn, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#),
434 DuplicatesOk, EncodeCrossCrate::No,
435 ),
436 ungated!(
437 allow, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#),
438 DuplicatesOk, EncodeCrossCrate::No,
439 ),
440 ungated!(
441 expect, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#),
442 DuplicatesOk, EncodeCrossCrate::No,
443 ),
444 ungated!(
445 forbid, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#),
446 DuplicatesOk, EncodeCrossCrate::No
447 ),
448 ungated!(
449 deny, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#),
450 DuplicatesOk, EncodeCrossCrate::No
451 ),
452 ungated!(
453 must_use, Normal, template!(Word, NameValueStr: "reason"),
454 FutureWarnFollowing, EncodeCrossCrate::Yes
455 ),
456 gated!(
457 must_not_suspend, Normal, template!(Word, NameValueStr: "reason"), WarnFollowing,
458 EncodeCrossCrate::Yes, experimental!(must_not_suspend)
459 ),
460 ungated!(
461 deprecated, Normal,
462 template!(
463 Word,
464 List: r#"/*opt*/ since = "version", /*opt*/ note = "reason""#,
465 NameValueStr: "reason"
466 ),
467 ErrorFollowing, EncodeCrossCrate::Yes
468 ),
469
470 ungated!(
472 crate_name, CrateLevel, template!(NameValueStr: "name"), FutureWarnFollowing,
473 EncodeCrossCrate::No,
474 ),
475 ungated!(
476 crate_type, CrateLevel, template!(NameValueStr: "bin|lib|..."), DuplicatesOk,
477 EncodeCrossCrate::No,
478 ),
479
480 ungated!(
482 link, Normal,
483 template!(List: r#"name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...", /*opt*/ import_name_type = "decorated|noprefix|undecorated""#),
484 DuplicatesOk,
485 EncodeCrossCrate::No,
486 ),
487 ungated!(
488 link_name, Normal, template!(NameValueStr: "name"),
489 FutureWarnPreceding, EncodeCrossCrate::Yes
490 ),
491 ungated!(no_link, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No),
492 ungated!(repr, Normal, template!(List: "C"), DuplicatesOk, EncodeCrossCrate::No),
493 gated!(rustc_align, Normal, template!(List: "alignment"), DuplicatesOk, EncodeCrossCrate::No, fn_align, experimental!(rustc_align)),
495 ungated!(unsafe(Edition2024) export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No),
496 ungated!(unsafe(Edition2024) link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No),
497 ungated!(unsafe(Edition2024) no_mangle, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No),
498 ungated!(used, Normal, template!(Word, List: "compiler|linker"), WarnFollowing, EncodeCrossCrate::No),
499 ungated!(link_ordinal, Normal, template!(List: "ordinal"), ErrorPreceding, EncodeCrossCrate::Yes),
500 ungated!(unsafe naked, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No),
501
502 ungated!(
504 recursion_limit, CrateLevel, template!(NameValueStr: "N"), FutureWarnFollowing,
505 EncodeCrossCrate::No
506 ),
507 ungated!(
508 type_length_limit, CrateLevel, template!(NameValueStr: "N"), FutureWarnFollowing,
509 EncodeCrossCrate::No
510 ),
511 gated!(
512 move_size_limit, CrateLevel, template!(NameValueStr: "N"), ErrorFollowing,
513 EncodeCrossCrate::No, large_assignments, experimental!(move_size_limit)
514 ),
515
516 ungated!(no_main, CrateLevel, template!(Word), WarnFollowing, EncodeCrossCrate::No),
518
519 ungated!(path, Normal, template!(NameValueStr: "file"), FutureWarnFollowing, EncodeCrossCrate::No),
521 ungated!(no_std, CrateLevel, template!(Word), WarnFollowing, EncodeCrossCrate::No),
522 ungated!(no_implicit_prelude, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No),
523 ungated!(non_exhaustive, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes),
524
525 ungated!(
527 windows_subsystem, CrateLevel,
528 template!(NameValueStr: "windows|console"), FutureWarnFollowing,
529 EncodeCrossCrate::No
530 ),
531 ungated!(panic_handler, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes), ungated!(inline, Normal, template!(Word, List: "always|never"), FutureWarnFollowing, EncodeCrossCrate::No),
535 ungated!(cold, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No),
536 ungated!(no_builtins, CrateLevel, template!(Word), WarnFollowing, EncodeCrossCrate::Yes),
537 ungated!(
538 target_feature, Normal, template!(List: r#"enable = "name""#),
539 DuplicatesOk, EncodeCrossCrate::No,
540 ),
541 ungated!(track_caller, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes),
542 ungated!(instruction_set, Normal, template!(List: "set"), ErrorPreceding, EncodeCrossCrate::No),
543 gated!(
544 no_sanitize, Normal,
545 template!(List: "address, kcfi, memory, thread"), DuplicatesOk,
546 EncodeCrossCrate::No, experimental!(no_sanitize)
547 ),
548 gated!(
549 coverage, Normal, template!(OneOf: &[sym::off, sym::on]),
550 ErrorPreceding, EncodeCrossCrate::No,
551 coverage_attribute, experimental!(coverage)
552 ),
553
554 ungated!(
555 doc, Normal, template!(List: "hidden|inline|...", NameValueStr: "string"), DuplicatesOk,
556 EncodeCrossCrate::Yes
557 ),
558
559 ungated!(
561 debugger_visualizer, Normal,
562 template!(List: r#"natvis_file = "...", gdb_script_file = "...""#),
563 DuplicatesOk, EncodeCrossCrate::No
564 ),
565 ungated!(collapse_debuginfo, Normal, template!(List: "no|external|yes"), ErrorFollowing,
566 EncodeCrossCrate::Yes
567 ),
568
569 gated!(
575 export_stable, Normal, template!(Word), WarnFollowing,
576 EncodeCrossCrate::No, experimental!(export_stable)
577 ),
578
579 gated!(
581 test_runner, CrateLevel, template!(List: "path"), ErrorFollowing,
582 EncodeCrossCrate::Yes, custom_test_frameworks,
583 "custom test frameworks are an unstable feature",
584 ),
585 gated!(
587 marker, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No,
588 marker_trait_attr, experimental!(marker)
589 ),
590 gated!(
591 thread_local, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No,
592 "`#[thread_local]` is an experimental feature, and does not currently handle destructors",
593 ),
594 gated!(
595 no_core, CrateLevel, template!(Word), WarnFollowing,
596 EncodeCrossCrate::No, experimental!(no_core)
597 ),
598 gated!(
600 optimize, Normal, template!(List: "none|size|speed"), ErrorPreceding,
601 EncodeCrossCrate::No, optimize_attribute, experimental!(optimize)
602 ),
603
604 gated!(
605 unsafe ffi_pure, Normal, template!(Word), WarnFollowing,
606 EncodeCrossCrate::No, experimental!(ffi_pure)
607 ),
608 gated!(
609 unsafe ffi_const, Normal, template!(Word), WarnFollowing,
610 EncodeCrossCrate::No, experimental!(ffi_const)
611 ),
612 gated!(
613 register_tool, CrateLevel, template!(List: "tool1, tool2, ..."), DuplicatesOk,
614 EncodeCrossCrate::No, experimental!(register_tool),
615 ),
616
617 gated!(
620 const_trait, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No, const_trait_impl,
621 "`const_trait` is a temporary placeholder for marking a trait that is suitable for `const` \
622 `impls` and all default bodies as `const`, which may be removed or renamed in the \
623 future."
624 ),
625 gated!(
627 deprecated_safe, Normal, template!(List: r#"since = "version", note = "...""#), ErrorFollowing,
628 EncodeCrossCrate::Yes, experimental!(deprecated_safe),
629 ),
630
631 gated!(
633 cfi_encoding, Normal, template!(NameValueStr: "encoding"), ErrorPreceding,
634 EncodeCrossCrate::Yes, experimental!(cfi_encoding)
635 ),
636
637 gated!(
639 coroutine, Normal, template!(Word), ErrorFollowing,
640 EncodeCrossCrate::No, coroutines, experimental!(coroutine)
641 ),
642
643 gated!(
646 patchable_function_entry, Normal, template!(List: "prefix_nops = m, entry_nops = n"), ErrorPreceding,
647 EncodeCrossCrate::Yes, experimental!(patchable_function_entry)
648 ),
649
650 gated!(
653 type_const, Normal, template!(Word), ErrorFollowing,
654 EncodeCrossCrate::Yes, min_generic_const_args, experimental!(type_const),
655 ),
656
657 gated!(
662 const_continue, Normal, template!(Word), ErrorFollowing,
663 EncodeCrossCrate::No, loop_match, experimental!(const_continue)
664 ),
665 gated!(
666 loop_match, Normal, template!(Word), ErrorFollowing,
667 EncodeCrossCrate::No, loop_match, experimental!(loop_match)
668 ),
669
670 ungated!(
675 feature, CrateLevel,
676 template!(List: "name1, name2, ..."), DuplicatesOk, EncodeCrossCrate::No,
677 ),
678 ungated!(
680 stable, Normal,
681 template!(List: r#"feature = "name", since = "version""#), DuplicatesOk, EncodeCrossCrate::No,
682 ),
683 ungated!(
684 unstable, Normal,
685 template!(List: r#"feature = "name", reason = "...", issue = "N""#), DuplicatesOk,
686 EncodeCrossCrate::Yes
687 ),
688 ungated!(
689 unstable_feature_bound, Normal, template!(Word, List: "feat1, feat2, ..."),
690 DuplicatesOk, EncodeCrossCrate::No,
691 ),
692 ungated!(
693 rustc_const_unstable, Normal, template!(List: r#"feature = "name""#),
694 DuplicatesOk, EncodeCrossCrate::Yes
695 ),
696 ungated!(
697 rustc_const_stable, Normal,
698 template!(List: r#"feature = "name""#), DuplicatesOk, EncodeCrossCrate::No,
699 ),
700 ungated!(
701 rustc_default_body_unstable, Normal,
702 template!(List: r#"feature = "name", reason = "...", issue = "N""#),
703 DuplicatesOk, EncodeCrossCrate::No
704 ),
705 gated!(
706 allow_internal_unstable, Normal, template!(Word, List: "feat1, feat2, ..."),
707 DuplicatesOk, EncodeCrossCrate::Yes,
708 "allow_internal_unstable side-steps feature gating and stability checks",
709 ),
710 gated!(
711 allow_internal_unsafe, Normal, template!(Word), WarnFollowing,
712 EncodeCrossCrate::No, "allow_internal_unsafe side-steps the unsafe_code lint",
713 ),
714 rustc_attr!(
715 rustc_allowed_through_unstable_modules, Normal, template!(NameValueStr: "deprecation message"),
716 WarnFollowing, EncodeCrossCrate::No,
717 "rustc_allowed_through_unstable_modules special cases accidental stabilizations of stable items \
718 through unstable paths"
719 ),
720 rustc_attr!(
721 rustc_deprecated_safe_2024, Normal, template!(List: r#"audit_that = "...""#),
722 ErrorFollowing, EncodeCrossCrate::Yes,
723 "`#[rustc_deprecated_safe_2024]` is used to declare functions unsafe across the edition 2024 boundary",
724 ),
725 rustc_attr!(
726 rustc_pub_transparent, Normal, template!(Word),
727 ErrorFollowing, EncodeCrossCrate::Yes,
728 "used internally to mark types with a `transparent` representation when it is guaranteed by the documentation",
729 ),
730
731
732 gated!(fundamental, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes, experimental!(fundamental)),
737 gated!(
738 may_dangle, Normal, template!(Word), WarnFollowing,
739 EncodeCrossCrate::No, dropck_eyepatch,
740 "`may_dangle` has unstable semantics and may be removed in the future",
741 ),
742
743 rustc_attr!(
744 rustc_never_type_options,
745 Normal,
746 template!(List: r#"/*opt*/ fallback = "unit|niko|never|no""#),
747 ErrorFollowing,
748 EncodeCrossCrate::No,
749 "`rustc_never_type_options` is used to experiment with never type fallback and work on \
750 never type stabilization"
751 ),
752
753 rustc_attr!(
758 rustc_allocator, Normal, template!(Word), WarnFollowing,
759 EncodeCrossCrate::No,
760 ),
761 rustc_attr!(
762 rustc_nounwind, Normal, template!(Word), WarnFollowing,
763 EncodeCrossCrate::No,
764 ),
765 rustc_attr!(
766 rustc_reallocator, Normal, template!(Word), WarnFollowing,
767 EncodeCrossCrate::No,
768 ),
769 rustc_attr!(
770 rustc_deallocator, Normal, template!(Word), WarnFollowing,
771 EncodeCrossCrate::No,
772 ),
773 rustc_attr!(
774 rustc_allocator_zeroed, Normal, template!(Word), WarnFollowing,
775 EncodeCrossCrate::No,
776 ),
777 gated!(
778 default_lib_allocator, Normal, template!(Word), WarnFollowing,
779 EncodeCrossCrate::No, allocator_internals, experimental!(default_lib_allocator),
780 ),
781 gated!(
782 needs_allocator, Normal, template!(Word), WarnFollowing,
783 EncodeCrossCrate::No, allocator_internals, experimental!(needs_allocator),
784 ),
785 gated!(
786 panic_runtime, CrateLevel, template!(Word), WarnFollowing,
787 EncodeCrossCrate::No, experimental!(panic_runtime)
788 ),
789 gated!(
790 needs_panic_runtime, CrateLevel, template!(Word), WarnFollowing,
791 EncodeCrossCrate::No, experimental!(needs_panic_runtime)
792 ),
793 gated!(
794 compiler_builtins, CrateLevel, template!(Word), WarnFollowing,
795 EncodeCrossCrate::No,
796 "the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate \
797 which contains compiler-rt intrinsics and will never be stable",
798 ),
799 gated!(
800 profiler_runtime, CrateLevel, template!(Word), WarnFollowing,
801 EncodeCrossCrate::No,
802 "the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate \
803 which contains the profiler runtime and will never be stable",
804 ),
805
806 gated!(
811 linkage, Normal, template!(NameValueStr: "external|internal|..."),
812 ErrorPreceding, EncodeCrossCrate::No,
813 "the `linkage` attribute is experimental and not portable across platforms",
814 ),
815 rustc_attr!(
816 rustc_std_internal_symbol, Normal, template!(Word), WarnFollowing,
817 EncodeCrossCrate::No,
818 ),
819
820 rustc_attr!(
825 rustc_builtin_macro, Normal,
826 template!(Word, List: "name, /*opt*/ attributes(name1, name2, ...)"), ErrorFollowing,
827 EncodeCrossCrate::Yes,
828 ),
829 rustc_attr!(
830 rustc_proc_macro_decls, Normal, template!(Word), WarnFollowing,
831 EncodeCrossCrate::No,
832 ),
833 rustc_attr!(
834 rustc_macro_transparency, Normal,
835 template!(NameValueStr: "transparent|semiopaque|opaque"), ErrorFollowing,
836 EncodeCrossCrate::Yes, "used internally for testing macro hygiene",
837 ),
838 rustc_attr!(
839 rustc_autodiff, Normal,
840 template!(Word, List: r#""...""#), DuplicatesOk,
841 EncodeCrossCrate::Yes,
842 ),
843 ungated!(
848 cfg_trace, Normal, template!(Word ), DuplicatesOk,
849 EncodeCrossCrate::No
850 ),
851 ungated!(
852 cfg_attr_trace, Normal, template!(Word ), DuplicatesOk,
853 EncodeCrossCrate::No
854 ),
855
856 rustc_attr!(
861 rustc_on_unimplemented, Normal,
862 template!(
863 List: r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#,
864 NameValueStr: "message"
865 ),
866 ErrorFollowing, EncodeCrossCrate::Yes,
867 "see `#[diagnostic::on_unimplemented]` for the stable equivalent of this attribute"
868 ),
869 rustc_attr!(
870 rustc_confusables, Normal,
871 template!(List: r#""name1", "name2", ..."#),
872 ErrorFollowing, EncodeCrossCrate::Yes,
873 ),
874 rustc_attr!(
876 rustc_conversion_suggestion, Normal, template!(Word),
877 WarnFollowing, EncodeCrossCrate::Yes,
878 ),
879 rustc_attr!(
882 rustc_trivial_field_reads, Normal, template!(Word),
883 WarnFollowing, EncodeCrossCrate::Yes,
884 ),
885 rustc_attr!(
888 rustc_lint_query_instability, Normal, template!(Word),
889 WarnFollowing, EncodeCrossCrate::Yes,
890 ),
891 rustc_attr!(
894 rustc_lint_untracked_query_information, Normal, template!(Word),
895 WarnFollowing, EncodeCrossCrate::Yes,
896 ),
897 rustc_attr!(
900 rustc_lint_diagnostics, Normal, template!(Word),
901 WarnFollowing, EncodeCrossCrate::Yes,
902 ),
903 rustc_attr!(
906 rustc_lint_opt_ty, Normal, template!(Word),
907 WarnFollowing, EncodeCrossCrate::Yes,
908 ),
909 rustc_attr!(
912 rustc_lint_opt_deny_field_access, Normal, template!(List: "message"),
913 WarnFollowing, EncodeCrossCrate::Yes,
914 ),
915
916 rustc_attr!(
921 rustc_promotable, Normal, template!(Word), WarnFollowing,
922 EncodeCrossCrate::No, ),
923 rustc_attr!(
924 rustc_legacy_const_generics, Normal, template!(List: "N"), ErrorFollowing,
925 EncodeCrossCrate::Yes,
926 ),
927 rustc_attr!(
929 rustc_do_not_const_check, Normal, template!(Word), WarnFollowing,
930 EncodeCrossCrate::Yes, "`#[rustc_do_not_const_check]` skips const-check for this function's body",
931 ),
932 rustc_attr!(
933 rustc_const_panic_str, Normal, template!(Word), WarnFollowing,
934 EncodeCrossCrate::Yes, "`#[rustc_const_panic_str]` ensures the argument to this function is &&str during const-check",
935 ),
936 rustc_attr!(
937 rustc_const_stable_indirect, Normal,
938 template!(Word),
939 WarnFollowing,
940 EncodeCrossCrate::No,
941 "this is an internal implementation detail",
942 ),
943 rustc_attr!(
944 rustc_intrinsic_const_stable_indirect, Normal,
945 template!(Word), WarnFollowing, EncodeCrossCrate::No, "this is an internal implementation detail",
946 ),
947 gated!(
948 rustc_allow_const_fn_unstable, Normal,
949 template!(Word, List: "feat1, feat2, ..."), DuplicatesOk, EncodeCrossCrate::No,
950 "rustc_allow_const_fn_unstable side-steps feature gating and stability checks"
951 ),
952
953 rustc_attr!(
958 rustc_layout_scalar_valid_range_start, Normal, template!(List: "value"), ErrorFollowing,
959 EncodeCrossCrate::Yes,
960 "the `#[rustc_layout_scalar_valid_range_start]` attribute is just used to enable \
961 niche optimizations in the standard library",
962 ),
963 rustc_attr!(
964 rustc_layout_scalar_valid_range_end, Normal, template!(List: "value"), ErrorFollowing,
965 EncodeCrossCrate::Yes,
966 "the `#[rustc_layout_scalar_valid_range_end]` attribute is just used to enable \
967 niche optimizations in the standard library",
968 ),
969 rustc_attr!(
970 rustc_nonnull_optimization_guaranteed, Normal, template!(Word), WarnFollowing,
971 EncodeCrossCrate::Yes,
972 "the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to document \
973 guaranteed niche optimizations in the standard library",
974 "the compiler does not even check whether the type indeed is being non-null-optimized; \
975 it is your responsibility to ensure that the attribute is only used on types that are optimized",
976 ),
977
978 gated!(
982 lang, Normal, template!(NameValueStr: "name"), DuplicatesOk, EncodeCrossCrate::No, lang_items,
983 "lang items are subject to change",
984 ),
985 rustc_attr!(
986 rustc_as_ptr, Normal, template!(Word), ErrorFollowing,
987 EncodeCrossCrate::Yes,
988 "`#[rustc_as_ptr]` is used to mark functions returning pointers to their inner allocations."
989 ),
990 rustc_attr!(
991 rustc_pass_by_value, Normal, template!(Word), ErrorFollowing,
992 EncodeCrossCrate::Yes,
993 "`#[rustc_pass_by_value]` is used to mark types that must be passed by value instead of reference."
994 ),
995 rustc_attr!(
996 rustc_never_returns_null_ptr, Normal, template!(Word), ErrorFollowing,
997 EncodeCrossCrate::Yes,
998 "`#[rustc_never_returns_null_ptr]` is used to mark functions returning non-null pointers."
999 ),
1000 rustc_attr!(
1001 rustc_no_implicit_autorefs, AttributeType::Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes,
1002 "`#[rustc_no_implicit_autorefs]` is used to mark functions for which an autoref to the dereference of a raw pointer should not be used as an argument."
1003 ),
1004 rustc_attr!(
1005 rustc_coherence_is_core, AttributeType::CrateLevel, template!(Word), ErrorFollowing, EncodeCrossCrate::No,
1006 "`#![rustc_coherence_is_core]` allows inherent methods on builtin types, only intended to be used in `core`."
1007 ),
1008 rustc_attr!(
1009 rustc_coinductive, AttributeType::Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No,
1010 "`#[rustc_coinductive]` changes a trait to be coinductive, allowing cycles in the trait solver."
1011 ),
1012 rustc_attr!(
1013 rustc_allow_incoherent_impl, AttributeType::Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::No,
1014 "`#[rustc_allow_incoherent_impl]` has to be added to all impl items of an incoherent inherent impl."
1015 ),
1016 rustc_attr!(
1017 rustc_preserve_ub_checks, AttributeType::CrateLevel, template!(Word), ErrorFollowing, EncodeCrossCrate::No,
1018 "`#![rustc_preserve_ub_checks]` prevents the designated crate from evaluating whether UB checks are enabled when optimizing MIR",
1019 ),
1020 rustc_attr!(
1021 rustc_deny_explicit_impl,
1022 AttributeType::Normal,
1023 template!(Word),
1024 ErrorFollowing,
1025 EncodeCrossCrate::No,
1026 "`#[rustc_deny_explicit_impl]` enforces that a trait can have no user-provided impls"
1027 ),
1028 rustc_attr!(
1029 rustc_do_not_implement_via_object,
1030 AttributeType::Normal,
1031 template!(Word),
1032 ErrorFollowing,
1033 EncodeCrossCrate::No,
1034 "`#[rustc_do_not_implement_via_object]` opts out of the automatic trait impl for trait objects \
1035 (`impl Trait for dyn Trait`)"
1036 ),
1037 rustc_attr!(
1038 rustc_has_incoherent_inherent_impls, AttributeType::Normal, template!(Word),
1039 ErrorFollowing, EncodeCrossCrate::Yes,
1040 "`#[rustc_has_incoherent_inherent_impls]` allows the addition of incoherent inherent impls for \
1041 the given type by annotating all impl items with `#[rustc_allow_incoherent_impl]`."
1042 ),
1043
1044 BuiltinAttribute {
1045 name: sym::rustc_diagnostic_item,
1046 encode_cross_crate: EncodeCrossCrate::Yes,
1048 type_: Normal,
1049 safety: AttributeSafety::Normal,
1050 template: template!(NameValueStr: "name"),
1051 duplicates: ErrorFollowing,
1052 gate: Gated{
1053 feature: sym::rustc_attrs,
1054 message: "use of an internal attribute",
1055 check: Features::rustc_attrs,
1056 notes: &["the `#[rustc_diagnostic_item]` attribute allows the compiler to reference types \
1057 from the standard library for diagnostic purposes"],
1058 },
1059 },
1060 gated!(
1061 prelude_import, Normal, template!(Word), WarnFollowing,
1063 EncodeCrossCrate::No, "`#[prelude_import]` is for use by rustc only",
1064 ),
1065 gated!(
1066 rustc_paren_sugar, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No,
1067 unboxed_closures, "unboxed_closures are still evolving",
1068 ),
1069 rustc_attr!(
1070 rustc_inherit_overflow_checks, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No,
1071 "the `#[rustc_inherit_overflow_checks]` attribute is just used to control \
1072 overflow checking behavior of several functions in the standard library that are inlined \
1073 across crates",
1074 ),
1075 rustc_attr!(
1076 rustc_reservation_impl, Normal,
1077 template!(NameValueStr: "reservation message"), ErrorFollowing, EncodeCrossCrate::Yes,
1078 "the `#[rustc_reservation_impl]` attribute is internally used \
1079 for reserving `impl<T> From<!> for T` as part of the effort to stabilize `!`"
1080 ),
1081 rustc_attr!(
1082 rustc_test_marker, Normal, template!(NameValueStr: "name"), WarnFollowing,
1083 EncodeCrossCrate::No, "the `#[rustc_test_marker]` attribute is used internally to track tests",
1084 ),
1085 rustc_attr!(
1086 rustc_unsafe_specialization_marker, Normal, template!(Word),
1087 WarnFollowing, EncodeCrossCrate::No,
1088 "the `#[rustc_unsafe_specialization_marker]` attribute is used to check specializations"
1089 ),
1090 rustc_attr!(
1091 rustc_specialization_trait, Normal, template!(Word),
1092 WarnFollowing, EncodeCrossCrate::No,
1093 "the `#[rustc_specialization_trait]` attribute is used to check specializations"
1094 ),
1095 rustc_attr!(
1096 rustc_main, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No,
1097 "the `#[rustc_main]` attribute is used internally to specify test entry point function",
1098 ),
1099 rustc_attr!(
1100 rustc_skip_during_method_dispatch, Normal, template!(List: "array, boxed_slice"), ErrorFollowing,
1101 EncodeCrossCrate::No,
1102 "the `#[rustc_skip_during_method_dispatch]` attribute is used to exclude a trait \
1103 from method dispatch when the receiver is of the following type, for compatibility in \
1104 editions < 2021 (array) or editions < 2024 (boxed_slice)."
1105 ),
1106 rustc_attr!(
1107 rustc_must_implement_one_of, Normal, template!(List: "function1, function2, ..."),
1108 ErrorFollowing, EncodeCrossCrate::No,
1109 "the `#[rustc_must_implement_one_of]` attribute is used to change minimal complete \
1110 definition of a trait. Its syntax and semantics are highly experimental and will be \
1111 subject to change before stabilization",
1112 ),
1113 rustc_attr!(
1114 rustc_doc_primitive, Normal, template!(NameValueStr: "primitive name"), ErrorFollowing,
1115 EncodeCrossCrate::Yes, "the `#[rustc_doc_primitive]` attribute is used by the standard library \
1116 to provide a way to generate documentation for primitive types",
1117 ),
1118 gated!(
1119 rustc_intrinsic, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes, intrinsics,
1120 "the `#[rustc_intrinsic]` attribute is used to declare intrinsics as function items",
1121 ),
1122 rustc_attr!(
1123 rustc_no_mir_inline, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes,
1124 "`#[rustc_no_mir_inline]` prevents the MIR inliner from inlining a function while not affecting codegen"
1125 ),
1126 rustc_attr!(
1127 rustc_force_inline, Normal, template!(Word, NameValueStr: "reason"), WarnFollowing, EncodeCrossCrate::Yes,
1128 "`#[rustc_force_inline]` forces a free function to be inlined"
1129 ),
1130
1131 rustc_attr!(TEST, rustc_effective_visibility, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes),
1136 rustc_attr!(
1137 TEST, rustc_outlives, Normal, template!(Word),
1138 WarnFollowing, EncodeCrossCrate::No
1139 ),
1140 rustc_attr!(
1141 TEST, rustc_capture_analysis, Normal, template!(Word),
1142 WarnFollowing, EncodeCrossCrate::No
1143 ),
1144 rustc_attr!(
1145 TEST, rustc_insignificant_dtor, Normal, template!(Word),
1146 WarnFollowing, EncodeCrossCrate::Yes
1147 ),
1148 rustc_attr!(
1149 TEST, rustc_no_implicit_bounds, CrateLevel, template!(Word),
1150 WarnFollowing, EncodeCrossCrate::No
1151 ),
1152 rustc_attr!(
1153 TEST, rustc_strict_coherence, Normal, template!(Word),
1154 WarnFollowing, EncodeCrossCrate::Yes
1155 ),
1156 rustc_attr!(
1157 TEST, rustc_variance, Normal, template!(Word),
1158 WarnFollowing, EncodeCrossCrate::No
1159 ),
1160 rustc_attr!(
1161 TEST, rustc_variance_of_opaques, Normal, template!(Word),
1162 WarnFollowing, EncodeCrossCrate::No
1163 ),
1164 rustc_attr!(
1165 TEST, rustc_hidden_type_of_opaques, Normal, template!(Word),
1166 WarnFollowing, EncodeCrossCrate::No
1167 ),
1168 rustc_attr!(
1169 TEST, rustc_layout, Normal, template!(List: "field1, field2, ..."),
1170 WarnFollowing, EncodeCrossCrate::Yes
1171 ),
1172 rustc_attr!(
1173 TEST, rustc_abi, Normal, template!(List: "field1, field2, ..."),
1174 WarnFollowing, EncodeCrossCrate::No
1175 ),
1176 rustc_attr!(
1177 TEST, rustc_regions, Normal, template!(Word),
1178 WarnFollowing, EncodeCrossCrate::No
1179 ),
1180 rustc_attr!(
1181 TEST, rustc_delayed_bug_from_inside_query, Normal,
1182 template!(Word),
1183 WarnFollowing, EncodeCrossCrate::No
1184 ),
1185 rustc_attr!(
1186 TEST, rustc_dump_user_args, Normal, template!(Word),
1187 WarnFollowing, EncodeCrossCrate::No
1188 ),
1189 rustc_attr!(
1190 TEST, rustc_evaluate_where_clauses, Normal, template!(Word), WarnFollowing,
1191 EncodeCrossCrate::Yes
1192 ),
1193 rustc_attr!(
1194 TEST, rustc_if_this_changed, Normal, template!(Word, List: "DepNode"), DuplicatesOk,
1195 EncodeCrossCrate::No
1196 ),
1197 rustc_attr!(
1198 TEST, rustc_then_this_would_need, Normal, template!(List: "DepNode"), DuplicatesOk,
1199 EncodeCrossCrate::No
1200 ),
1201 rustc_attr!(
1202 TEST, rustc_clean, Normal,
1203 template!(List: r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#),
1204 DuplicatesOk, EncodeCrossCrate::No
1205 ),
1206 rustc_attr!(
1207 TEST, rustc_partition_reused, Normal,
1208 template!(List: r#"cfg = "...", module = "...""#), DuplicatesOk, EncodeCrossCrate::No
1209 ),
1210 rustc_attr!(
1211 TEST, rustc_partition_codegened, Normal,
1212 template!(List: r#"cfg = "...", module = "...""#), DuplicatesOk, EncodeCrossCrate::No
1213 ),
1214 rustc_attr!(
1215 TEST, rustc_expected_cgu_reuse, Normal,
1216 template!(List: r#"cfg = "...", module = "...", kind = "...""#), DuplicatesOk,
1217 EncodeCrossCrate::No
1218 ),
1219 rustc_attr!(
1220 TEST, rustc_symbol_name, Normal, template!(Word),
1221 WarnFollowing, EncodeCrossCrate::No
1222 ),
1223 rustc_attr!(
1224 TEST, rustc_def_path, Normal, template!(Word),
1225 WarnFollowing, EncodeCrossCrate::No
1226 ),
1227 rustc_attr!(
1228 TEST, rustc_mir, Normal, template!(List: "arg1, arg2, ..."),
1229 DuplicatesOk, EncodeCrossCrate::Yes
1230 ),
1231 gated!(
1232 custom_mir, Normal, template!(List: r#"dialect = "...", phase = "...""#),
1233 ErrorFollowing, EncodeCrossCrate::No,
1234 "the `#[custom_mir]` attribute is just used for the Rust test suite",
1235 ),
1236 rustc_attr!(
1237 TEST, rustc_dump_item_bounds, Normal, template!(Word),
1238 WarnFollowing, EncodeCrossCrate::No
1239 ),
1240 rustc_attr!(
1241 TEST, rustc_dump_predicates, Normal, template!(Word),
1242 WarnFollowing, EncodeCrossCrate::No
1243 ),
1244 rustc_attr!(
1245 TEST, rustc_dump_def_parents, Normal, template!(Word),
1246 WarnFollowing, EncodeCrossCrate::No
1247 ),
1248 rustc_attr!(
1249 TEST, rustc_object_lifetime_default, Normal, template!(Word),
1250 WarnFollowing, EncodeCrossCrate::No
1251 ),
1252 rustc_attr!(
1253 TEST, rustc_dump_vtable, Normal, template!(Word),
1254 WarnFollowing, EncodeCrossCrate::No
1255 ),
1256 rustc_attr!(
1257 TEST, rustc_dummy, Normal, template!(Word ),
1258 DuplicatesOk, EncodeCrossCrate::No
1259 ),
1260 gated!(
1261 omit_gdb_pretty_printer_section, Normal, template!(Word),
1262 WarnFollowing, EncodeCrossCrate::No,
1263 "the `#[omit_gdb_pretty_printer_section]` attribute is just used for the Rust test suite",
1264 ),
1265 rustc_attr!(
1266 TEST, pattern_complexity_limit, CrateLevel, template!(NameValueStr: "N"),
1267 ErrorFollowing, EncodeCrossCrate::No,
1268 ),
1269];
1270
1271pub fn is_builtin_attr_name(name: Symbol) -> bool {
1272 BUILTIN_ATTRIBUTE_MAP.get(&name).is_some()
1273}
1274
1275pub fn encode_cross_crate(name: Symbol) -> bool {
1278 if let Some(attr) = BUILTIN_ATTRIBUTE_MAP.get(&name) {
1279 attr.encode_cross_crate == EncodeCrossCrate::Yes
1280 } else {
1281 true
1282 }
1283}
1284
1285pub fn is_valid_for_get_attr(name: Symbol) -> bool {
1286 BUILTIN_ATTRIBUTE_MAP.get(&name).is_some_and(|attr| match attr.duplicates {
1287 WarnFollowing | ErrorFollowing | ErrorPreceding | FutureWarnFollowing
1288 | FutureWarnPreceding => true,
1289 DuplicatesOk | WarnFollowingWordOnly => false,
1290 })
1291}
1292
1293pub static BUILTIN_ATTRIBUTE_MAP: LazyLock<FxHashMap<Symbol, &BuiltinAttribute>> =
1294 LazyLock::new(|| {
1295 let mut map = FxHashMap::default();
1296 for attr in BUILTIN_ATTRIBUTES.iter() {
1297 if map.insert(attr.name, attr).is_some() {
1298 panic!("duplicate builtin attribute `{}`", attr.name);
1299 }
1300 }
1301 map
1302 });
1303
1304pub fn is_stable_diagnostic_attribute(sym: Symbol, _features: &Features) -> bool {
1305 match sym {
1306 sym::on_unimplemented | sym::do_not_recommend => true,
1307 _ => false,
1308 }
1309}