1use std::sync::LazyLock;
4
5use AttributeDuplicates::*;
6use AttributeGate::*;
7use AttributeType::*;
8use rustc_attr_data_structures::EncodeCrossCrate;
9use rustc_data_structures::fx::FxHashMap;
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!(align, Normal, template!(List: "alignment"), DuplicatesOk, EncodeCrossCrate::No, fn_align, experimental!(align)),
494 ungated!(unsafe(Edition2024) export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No),
495 ungated!(unsafe(Edition2024) link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding, EncodeCrossCrate::No),
496 ungated!(unsafe(Edition2024) no_mangle, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No),
497 ungated!(used, Normal, template!(Word, List: "compiler|linker"), WarnFollowing, EncodeCrossCrate::No),
498 ungated!(link_ordinal, Normal, template!(List: "ordinal"), ErrorPreceding, EncodeCrossCrate::Yes),
499 ungated!(unsafe naked, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No),
500
501 ungated!(
503 recursion_limit, CrateLevel, template!(NameValueStr: "N"), FutureWarnFollowing,
504 EncodeCrossCrate::No
505 ),
506 ungated!(
507 type_length_limit, CrateLevel, template!(NameValueStr: "N"), FutureWarnFollowing,
508 EncodeCrossCrate::No
509 ),
510 gated!(
511 move_size_limit, CrateLevel, template!(NameValueStr: "N"), ErrorFollowing,
512 EncodeCrossCrate::No, large_assignments, experimental!(move_size_limit)
513 ),
514
515 ungated!(no_main, CrateLevel, template!(Word), WarnFollowing, EncodeCrossCrate::No),
517
518 ungated!(path, Normal, template!(NameValueStr: "file"), FutureWarnFollowing, EncodeCrossCrate::No),
520 ungated!(no_std, CrateLevel, template!(Word), WarnFollowing, EncodeCrossCrate::No),
521 ungated!(no_implicit_prelude, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No),
522 ungated!(non_exhaustive, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes),
523
524 ungated!(
526 windows_subsystem, CrateLevel,
527 template!(NameValueStr: "windows|console"), FutureWarnFollowing,
528 EncodeCrossCrate::No
529 ),
530 ungated!(panic_handler, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes), ungated!(inline, Normal, template!(Word, List: "always|never"), FutureWarnFollowing, EncodeCrossCrate::No),
534 ungated!(cold, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No),
535 ungated!(no_builtins, CrateLevel, template!(Word), WarnFollowing, EncodeCrossCrate::Yes),
536 ungated!(
537 target_feature, Normal, template!(List: r#"enable = "name""#),
538 DuplicatesOk, EncodeCrossCrate::No,
539 ),
540 ungated!(track_caller, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes),
541 ungated!(instruction_set, Normal, template!(List: "set"), ErrorPreceding, EncodeCrossCrate::No),
542 gated!(
543 no_sanitize, Normal,
544 template!(List: "address, kcfi, memory, thread"), DuplicatesOk,
545 EncodeCrossCrate::No, experimental!(no_sanitize)
546 ),
547 gated!(
548 coverage, Normal, template!(OneOf: &[sym::off, sym::on]),
549 ErrorPreceding, EncodeCrossCrate::No,
550 coverage_attribute, experimental!(coverage)
551 ),
552
553 ungated!(
554 doc, Normal, template!(List: "hidden|inline|...", NameValueStr: "string"), DuplicatesOk,
555 EncodeCrossCrate::Yes
556 ),
557
558 ungated!(
560 debugger_visualizer, Normal,
561 template!(List: r#"natvis_file = "...", gdb_script_file = "...""#),
562 DuplicatesOk, EncodeCrossCrate::No
563 ),
564 ungated!(collapse_debuginfo, Normal, template!(List: "no|external|yes"), ErrorFollowing,
565 EncodeCrossCrate::Yes
566 ),
567
568 gated!(
574 export_stable, Normal, template!(Word), WarnFollowing,
575 EncodeCrossCrate::No, experimental!(export_stable)
576 ),
577
578 gated!(
580 test_runner, CrateLevel, template!(List: "path"), ErrorFollowing,
581 EncodeCrossCrate::Yes, custom_test_frameworks,
582 "custom test frameworks are an unstable feature",
583 ),
584 gated!(
586 marker, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No,
587 marker_trait_attr, experimental!(marker)
588 ),
589 gated!(
590 thread_local, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No,
591 "`#[thread_local]` is an experimental feature, and does not currently handle destructors",
592 ),
593 gated!(
594 no_core, CrateLevel, template!(Word), WarnFollowing,
595 EncodeCrossCrate::No, experimental!(no_core)
596 ),
597 gated!(
599 optimize, Normal, template!(List: "none|size|speed"), ErrorPreceding,
600 EncodeCrossCrate::No, optimize_attribute, experimental!(optimize)
601 ),
602
603 gated!(
604 unsafe ffi_pure, Normal, template!(Word), WarnFollowing,
605 EncodeCrossCrate::No, experimental!(ffi_pure)
606 ),
607 gated!(
608 unsafe ffi_const, Normal, template!(Word), WarnFollowing,
609 EncodeCrossCrate::No, experimental!(ffi_const)
610 ),
611 gated!(
612 register_tool, CrateLevel, template!(List: "tool1, tool2, ..."), DuplicatesOk,
613 EncodeCrossCrate::No, experimental!(register_tool),
614 ),
615
616 gated!(
619 const_trait, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No, const_trait_impl,
620 "`const_trait` is a temporary placeholder for marking a trait that is suitable for `const` \
621 `impls` and all default bodies as `const`, which may be removed or renamed in the \
622 future."
623 ),
624 gated!(
626 deprecated_safe, Normal, template!(List: r#"since = "version", note = "...""#), ErrorFollowing,
627 EncodeCrossCrate::Yes, experimental!(deprecated_safe),
628 ),
629
630 gated!(
632 cfi_encoding, Normal, template!(NameValueStr: "encoding"), ErrorPreceding,
633 EncodeCrossCrate::Yes, experimental!(cfi_encoding)
634 ),
635
636 gated!(
638 coroutine, Normal, template!(Word), ErrorFollowing,
639 EncodeCrossCrate::No, coroutines, experimental!(coroutine)
640 ),
641
642 gated!(
645 patchable_function_entry, Normal, template!(List: "prefix_nops = m, entry_nops = n"), ErrorPreceding,
646 EncodeCrossCrate::Yes, experimental!(patchable_function_entry)
647 ),
648
649 gated!(
652 type_const, Normal, template!(Word), ErrorFollowing,
653 EncodeCrossCrate::Yes, min_generic_const_args, experimental!(type_const),
654 ),
655
656 gated!(
661 const_continue, Normal, template!(Word), ErrorFollowing,
662 EncodeCrossCrate::No, loop_match, experimental!(const_continue)
663 ),
664 gated!(
665 loop_match, Normal, template!(Word), ErrorFollowing,
666 EncodeCrossCrate::No, loop_match, experimental!(loop_match)
667 ),
668
669 ungated!(
674 feature, CrateLevel,
675 template!(List: "name1, name2, ..."), DuplicatesOk, EncodeCrossCrate::No,
676 ),
677 ungated!(
679 stable, Normal,
680 template!(List: r#"feature = "name", since = "version""#), DuplicatesOk, EncodeCrossCrate::No,
681 ),
682 ungated!(
683 unstable, Normal,
684 template!(List: r#"feature = "name", reason = "...", issue = "N""#), DuplicatesOk,
685 EncodeCrossCrate::Yes
686 ),
687 ungated!(
688 unstable_feature_bound, Normal, template!(Word, List: "feat1, feat2, ..."),
689 DuplicatesOk, EncodeCrossCrate::No,
690 ),
691 ungated!(
692 rustc_const_unstable, Normal, template!(List: r#"feature = "name""#),
693 DuplicatesOk, EncodeCrossCrate::Yes
694 ),
695 ungated!(
696 rustc_const_stable, Normal,
697 template!(List: r#"feature = "name""#), DuplicatesOk, EncodeCrossCrate::No,
698 ),
699 ungated!(
700 rustc_default_body_unstable, Normal,
701 template!(List: r#"feature = "name", reason = "...", issue = "N""#),
702 DuplicatesOk, EncodeCrossCrate::No
703 ),
704 gated!(
705 allow_internal_unstable, Normal, template!(Word, List: "feat1, feat2, ..."),
706 DuplicatesOk, EncodeCrossCrate::Yes,
707 "allow_internal_unstable side-steps feature gating and stability checks",
708 ),
709 gated!(
710 allow_internal_unsafe, Normal, template!(Word), WarnFollowing,
711 EncodeCrossCrate::No, "allow_internal_unsafe side-steps the unsafe_code lint",
712 ),
713 rustc_attr!(
714 rustc_allowed_through_unstable_modules, Normal, template!(NameValueStr: "deprecation message"),
715 WarnFollowing, EncodeCrossCrate::No,
716 "rustc_allowed_through_unstable_modules special cases accidental stabilizations of stable items \
717 through unstable paths"
718 ),
719 rustc_attr!(
720 rustc_deprecated_safe_2024, Normal, template!(List: r#"audit_that = "...""#),
721 ErrorFollowing, EncodeCrossCrate::Yes,
722 "`#[rustc_deprecated_safe_2024]` is used to declare functions unsafe across the edition 2024 boundary",
723 ),
724 rustc_attr!(
725 rustc_pub_transparent, Normal, template!(Word),
726 ErrorFollowing, EncodeCrossCrate::Yes,
727 "used internally to mark types with a `transparent` representation when it is guaranteed by the documentation",
728 ),
729
730
731 gated!(fundamental, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes, experimental!(fundamental)),
736 gated!(
737 may_dangle, Normal, template!(Word), WarnFollowing,
738 EncodeCrossCrate::No, dropck_eyepatch,
739 "`may_dangle` has unstable semantics and may be removed in the future",
740 ),
741
742 rustc_attr!(
743 rustc_never_type_options,
744 Normal,
745 template!(List: r#"/*opt*/ fallback = "unit|niko|never|no""#),
746 ErrorFollowing,
747 EncodeCrossCrate::No,
748 "`rustc_never_type_options` is used to experiment with never type fallback and work on \
749 never type stabilization"
750 ),
751
752 rustc_attr!(
757 rustc_allocator, Normal, template!(Word), WarnFollowing,
758 EncodeCrossCrate::No,
759 ),
760 rustc_attr!(
761 rustc_nounwind, Normal, template!(Word), WarnFollowing,
762 EncodeCrossCrate::No,
763 ),
764 rustc_attr!(
765 rustc_reallocator, Normal, template!(Word), WarnFollowing,
766 EncodeCrossCrate::No,
767 ),
768 rustc_attr!(
769 rustc_deallocator, Normal, template!(Word), WarnFollowing,
770 EncodeCrossCrate::No,
771 ),
772 rustc_attr!(
773 rustc_allocator_zeroed, Normal, template!(Word), WarnFollowing,
774 EncodeCrossCrate::No,
775 ),
776 gated!(
777 default_lib_allocator, Normal, template!(Word), WarnFollowing,
778 EncodeCrossCrate::No, allocator_internals, experimental!(default_lib_allocator),
779 ),
780 gated!(
781 needs_allocator, Normal, template!(Word), WarnFollowing,
782 EncodeCrossCrate::No, allocator_internals, experimental!(needs_allocator),
783 ),
784 gated!(
785 panic_runtime, CrateLevel, template!(Word), WarnFollowing,
786 EncodeCrossCrate::No, experimental!(panic_runtime)
787 ),
788 gated!(
789 needs_panic_runtime, CrateLevel, template!(Word), WarnFollowing,
790 EncodeCrossCrate::No, experimental!(needs_panic_runtime)
791 ),
792 gated!(
793 compiler_builtins, CrateLevel, template!(Word), WarnFollowing,
794 EncodeCrossCrate::No,
795 "the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate \
796 which contains compiler-rt intrinsics and will never be stable",
797 ),
798 gated!(
799 profiler_runtime, CrateLevel, template!(Word), WarnFollowing,
800 EncodeCrossCrate::No,
801 "the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate \
802 which contains the profiler runtime and will never be stable",
803 ),
804
805 gated!(
810 linkage, Normal, template!(NameValueStr: "external|internal|..."),
811 ErrorPreceding, EncodeCrossCrate::No,
812 "the `linkage` attribute is experimental and not portable across platforms",
813 ),
814 rustc_attr!(
815 rustc_std_internal_symbol, Normal, template!(Word), WarnFollowing,
816 EncodeCrossCrate::No,
817 ),
818
819 rustc_attr!(
824 rustc_builtin_macro, Normal,
825 template!(Word, List: "name, /*opt*/ attributes(name1, name2, ...)"), ErrorFollowing,
826 EncodeCrossCrate::Yes,
827 ),
828 rustc_attr!(
829 rustc_proc_macro_decls, Normal, template!(Word), WarnFollowing,
830 EncodeCrossCrate::No,
831 ),
832 rustc_attr!(
833 rustc_macro_transparency, Normal,
834 template!(NameValueStr: "transparent|semiopaque|opaque"), ErrorFollowing,
835 EncodeCrossCrate::Yes, "used internally for testing macro hygiene",
836 ),
837 rustc_attr!(
838 rustc_autodiff, Normal,
839 template!(Word, List: r#""...""#), DuplicatesOk,
840 EncodeCrossCrate::Yes,
841 ),
842 ungated!(
847 cfg_trace, Normal, template!(Word ), DuplicatesOk,
848 EncodeCrossCrate::No
849 ),
850 ungated!(
851 cfg_attr_trace, Normal, template!(Word ), DuplicatesOk,
852 EncodeCrossCrate::No
853 ),
854
855 rustc_attr!(
860 rustc_on_unimplemented, Normal,
861 template!(
862 List: r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#,
863 NameValueStr: "message"
864 ),
865 ErrorFollowing, EncodeCrossCrate::Yes,
866 "see `#[diagnostic::on_unimplemented]` for the stable equivalent of this attribute"
867 ),
868 rustc_attr!(
869 rustc_confusables, Normal,
870 template!(List: r#""name1", "name2", ..."#),
871 ErrorFollowing, EncodeCrossCrate::Yes,
872 ),
873 rustc_attr!(
875 rustc_conversion_suggestion, Normal, template!(Word),
876 WarnFollowing, EncodeCrossCrate::Yes,
877 ),
878 rustc_attr!(
881 rustc_trivial_field_reads, Normal, template!(Word),
882 WarnFollowing, EncodeCrossCrate::Yes,
883 ),
884 rustc_attr!(
887 rustc_lint_query_instability, Normal, template!(Word),
888 WarnFollowing, EncodeCrossCrate::Yes,
889 ),
890 rustc_attr!(
893 rustc_lint_untracked_query_information, Normal, template!(Word),
894 WarnFollowing, EncodeCrossCrate::Yes,
895 ),
896 rustc_attr!(
899 rustc_lint_diagnostics, Normal, template!(Word),
900 WarnFollowing, EncodeCrossCrate::Yes,
901 ),
902 rustc_attr!(
905 rustc_lint_opt_ty, Normal, template!(Word),
906 WarnFollowing, EncodeCrossCrate::Yes,
907 ),
908 rustc_attr!(
911 rustc_lint_opt_deny_field_access, Normal, template!(List: "message"),
912 WarnFollowing, EncodeCrossCrate::Yes,
913 ),
914
915 rustc_attr!(
920 rustc_promotable, Normal, template!(Word), WarnFollowing,
921 EncodeCrossCrate::No, ),
922 rustc_attr!(
923 rustc_legacy_const_generics, Normal, template!(List: "N"), ErrorFollowing,
924 EncodeCrossCrate::Yes,
925 ),
926 rustc_attr!(
928 rustc_do_not_const_check, Normal, template!(Word), WarnFollowing,
929 EncodeCrossCrate::Yes, "`#[rustc_do_not_const_check]` skips const-check for this function's body",
930 ),
931 rustc_attr!(
932 rustc_const_panic_str, Normal, template!(Word), WarnFollowing,
933 EncodeCrossCrate::Yes, "`#[rustc_const_panic_str]` ensures the argument to this function is &&str during const-check",
934 ),
935 rustc_attr!(
936 rustc_const_stable_indirect, Normal,
937 template!(Word),
938 WarnFollowing,
939 EncodeCrossCrate::No,
940 "this is an internal implementation detail",
941 ),
942 rustc_attr!(
943 rustc_intrinsic_const_stable_indirect, Normal,
944 template!(Word), WarnFollowing, EncodeCrossCrate::No, "this is an internal implementation detail",
945 ),
946 gated!(
947 rustc_allow_const_fn_unstable, Normal,
948 template!(Word, List: "feat1, feat2, ..."), DuplicatesOk, EncodeCrossCrate::No,
949 "rustc_allow_const_fn_unstable side-steps feature gating and stability checks"
950 ),
951
952 rustc_attr!(
957 rustc_layout_scalar_valid_range_start, Normal, template!(List: "value"), ErrorFollowing,
958 EncodeCrossCrate::Yes,
959 "the `#[rustc_layout_scalar_valid_range_start]` attribute is just used to enable \
960 niche optimizations in the standard library",
961 ),
962 rustc_attr!(
963 rustc_layout_scalar_valid_range_end, Normal, template!(List: "value"), ErrorFollowing,
964 EncodeCrossCrate::Yes,
965 "the `#[rustc_layout_scalar_valid_range_end]` attribute is just used to enable \
966 niche optimizations in the standard library",
967 ),
968 rustc_attr!(
969 rustc_nonnull_optimization_guaranteed, Normal, template!(Word), WarnFollowing,
970 EncodeCrossCrate::Yes,
971 "the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to document \
972 guaranteed niche optimizations in the standard library",
973 "the compiler does not even check whether the type indeed is being non-null-optimized; \
974 it is your responsibility to ensure that the attribute is only used on types that are optimized",
975 ),
976
977 gated!(
981 lang, Normal, template!(NameValueStr: "name"), DuplicatesOk, EncodeCrossCrate::No, lang_items,
982 "lang items are subject to change",
983 ),
984 rustc_attr!(
985 rustc_as_ptr, Normal, template!(Word), ErrorFollowing,
986 EncodeCrossCrate::Yes,
987 "`#[rustc_as_ptr]` is used to mark functions returning pointers to their inner allocations."
988 ),
989 rustc_attr!(
990 rustc_pass_by_value, Normal, template!(Word), ErrorFollowing,
991 EncodeCrossCrate::Yes,
992 "`#[rustc_pass_by_value]` is used to mark types that must be passed by value instead of reference."
993 ),
994 rustc_attr!(
995 rustc_never_returns_null_ptr, Normal, template!(Word), ErrorFollowing,
996 EncodeCrossCrate::Yes,
997 "`#[rustc_never_returns_null_ptr]` is used to mark functions returning non-null pointers."
998 ),
999 rustc_attr!(
1000 rustc_no_implicit_autorefs, AttributeType::Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes,
1001 "`#[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."
1002 ),
1003 rustc_attr!(
1004 rustc_coherence_is_core, AttributeType::CrateLevel, template!(Word), ErrorFollowing, EncodeCrossCrate::No,
1005 "`#![rustc_coherence_is_core]` allows inherent methods on builtin types, only intended to be used in `core`."
1006 ),
1007 rustc_attr!(
1008 rustc_coinductive, AttributeType::Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No,
1009 "`#[rustc_coinductive]` changes a trait to be coinductive, allowing cycles in the trait solver."
1010 ),
1011 rustc_attr!(
1012 rustc_allow_incoherent_impl, AttributeType::Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::No,
1013 "`#[rustc_allow_incoherent_impl]` has to be added to all impl items of an incoherent inherent impl."
1014 ),
1015 rustc_attr!(
1016 rustc_preserve_ub_checks, AttributeType::CrateLevel, template!(Word), ErrorFollowing, EncodeCrossCrate::No,
1017 "`#![rustc_preserve_ub_checks]` prevents the designated crate from evaluating whether UB checks are enabled when optimizing MIR",
1018 ),
1019 rustc_attr!(
1020 rustc_deny_explicit_impl,
1021 AttributeType::Normal,
1022 template!(Word),
1023 ErrorFollowing,
1024 EncodeCrossCrate::No,
1025 "`#[rustc_deny_explicit_impl]` enforces that a trait can have no user-provided impls"
1026 ),
1027 rustc_attr!(
1028 rustc_do_not_implement_via_object,
1029 AttributeType::Normal,
1030 template!(Word),
1031 ErrorFollowing,
1032 EncodeCrossCrate::No,
1033 "`#[rustc_do_not_implement_via_object]` opts out of the automatic trait impl for trait objects \
1034 (`impl Trait for dyn Trait`)"
1035 ),
1036 rustc_attr!(
1037 rustc_has_incoherent_inherent_impls, AttributeType::Normal, template!(Word),
1038 ErrorFollowing, EncodeCrossCrate::Yes,
1039 "`#[rustc_has_incoherent_inherent_impls]` allows the addition of incoherent inherent impls for \
1040 the given type by annotating all impl items with `#[rustc_allow_incoherent_impl]`."
1041 ),
1042
1043 BuiltinAttribute {
1044 name: sym::rustc_diagnostic_item,
1045 encode_cross_crate: EncodeCrossCrate::Yes,
1047 type_: Normal,
1048 safety: AttributeSafety::Normal,
1049 template: template!(NameValueStr: "name"),
1050 duplicates: ErrorFollowing,
1051 gate: Gated{
1052 feature: sym::rustc_attrs,
1053 message: "use of an internal attribute",
1054 check: Features::rustc_attrs,
1055 notes: &["the `#[rustc_diagnostic_item]` attribute allows the compiler to reference types \
1056 from the standard library for diagnostic purposes"],
1057 },
1058 },
1059 gated!(
1060 prelude_import, Normal, template!(Word), WarnFollowing,
1062 EncodeCrossCrate::No, "`#[prelude_import]` is for use by rustc only",
1063 ),
1064 gated!(
1065 rustc_paren_sugar, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No,
1066 unboxed_closures, "unboxed_closures are still evolving",
1067 ),
1068 rustc_attr!(
1069 rustc_inherit_overflow_checks, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No,
1070 "the `#[rustc_inherit_overflow_checks]` attribute is just used to control \
1071 overflow checking behavior of several functions in the standard library that are inlined \
1072 across crates",
1073 ),
1074 rustc_attr!(
1075 rustc_reservation_impl, Normal,
1076 template!(NameValueStr: "reservation message"), ErrorFollowing, EncodeCrossCrate::Yes,
1077 "the `#[rustc_reservation_impl]` attribute is internally used \
1078 for reserving `impl<T> From<!> for T` as part of the effort to stabilize `!`"
1079 ),
1080 rustc_attr!(
1081 rustc_test_marker, Normal, template!(NameValueStr: "name"), WarnFollowing,
1082 EncodeCrossCrate::No, "the `#[rustc_test_marker]` attribute is used internally to track tests",
1083 ),
1084 rustc_attr!(
1085 rustc_unsafe_specialization_marker, Normal, template!(Word),
1086 WarnFollowing, EncodeCrossCrate::No,
1087 "the `#[rustc_unsafe_specialization_marker]` attribute is used to check specializations"
1088 ),
1089 rustc_attr!(
1090 rustc_specialization_trait, Normal, template!(Word),
1091 WarnFollowing, EncodeCrossCrate::No,
1092 "the `#[rustc_specialization_trait]` attribute is used to check specializations"
1093 ),
1094 rustc_attr!(
1095 rustc_main, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No,
1096 "the `#[rustc_main]` attribute is used internally to specify test entry point function",
1097 ),
1098 rustc_attr!(
1099 rustc_skip_during_method_dispatch, Normal, template!(List: "array, boxed_slice"), ErrorFollowing,
1100 EncodeCrossCrate::No,
1101 "the `#[rustc_skip_during_method_dispatch]` attribute is used to exclude a trait \
1102 from method dispatch when the receiver is of the following type, for compatibility in \
1103 editions < 2021 (array) or editions < 2024 (boxed_slice)."
1104 ),
1105 rustc_attr!(
1106 rustc_must_implement_one_of, Normal, template!(List: "function1, function2, ..."),
1107 ErrorFollowing, EncodeCrossCrate::No,
1108 "the `#[rustc_must_implement_one_of]` attribute is used to change minimal complete \
1109 definition of a trait. Its syntax and semantics are highly experimental and will be \
1110 subject to change before stabilization",
1111 ),
1112 rustc_attr!(
1113 rustc_doc_primitive, Normal, template!(NameValueStr: "primitive name"), ErrorFollowing,
1114 EncodeCrossCrate::Yes, "the `#[rustc_doc_primitive]` attribute is used by the standard library \
1115 to provide a way to generate documentation for primitive types",
1116 ),
1117 gated!(
1118 rustc_intrinsic, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes, intrinsics,
1119 "the `#[rustc_intrinsic]` attribute is used to declare intrinsics as function items",
1120 ),
1121 rustc_attr!(
1122 rustc_no_mir_inline, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes,
1123 "`#[rustc_no_mir_inline]` prevents the MIR inliner from inlining a function while not affecting codegen"
1124 ),
1125 rustc_attr!(
1126 rustc_force_inline, Normal, template!(Word, NameValueStr: "reason"), WarnFollowing, EncodeCrossCrate::Yes,
1127 "`#[rustc_force_inline]` forces a free function to be inlined"
1128 ),
1129
1130 rustc_attr!(TEST, rustc_effective_visibility, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes),
1135 rustc_attr!(
1136 TEST, rustc_outlives, Normal, template!(Word),
1137 WarnFollowing, EncodeCrossCrate::No
1138 ),
1139 rustc_attr!(
1140 TEST, rustc_capture_analysis, Normal, template!(Word),
1141 WarnFollowing, EncodeCrossCrate::No
1142 ),
1143 rustc_attr!(
1144 TEST, rustc_insignificant_dtor, Normal, template!(Word),
1145 WarnFollowing, EncodeCrossCrate::Yes
1146 ),
1147 rustc_attr!(
1148 TEST, rustc_no_implicit_bounds, CrateLevel, template!(Word),
1149 WarnFollowing, EncodeCrossCrate::No
1150 ),
1151 rustc_attr!(
1152 TEST, rustc_strict_coherence, Normal, template!(Word),
1153 WarnFollowing, EncodeCrossCrate::Yes
1154 ),
1155 rustc_attr!(
1156 TEST, rustc_variance, Normal, template!(Word),
1157 WarnFollowing, EncodeCrossCrate::No
1158 ),
1159 rustc_attr!(
1160 TEST, rustc_variance_of_opaques, Normal, template!(Word),
1161 WarnFollowing, EncodeCrossCrate::No
1162 ),
1163 rustc_attr!(
1164 TEST, rustc_hidden_type_of_opaques, Normal, template!(Word),
1165 WarnFollowing, EncodeCrossCrate::No
1166 ),
1167 rustc_attr!(
1168 TEST, rustc_layout, Normal, template!(List: "field1, field2, ..."),
1169 WarnFollowing, EncodeCrossCrate::Yes
1170 ),
1171 rustc_attr!(
1172 TEST, rustc_abi, Normal, template!(List: "field1, field2, ..."),
1173 WarnFollowing, EncodeCrossCrate::No
1174 ),
1175 rustc_attr!(
1176 TEST, rustc_regions, Normal, template!(Word),
1177 WarnFollowing, EncodeCrossCrate::No
1178 ),
1179 rustc_attr!(
1180 TEST, rustc_delayed_bug_from_inside_query, Normal,
1181 template!(Word),
1182 WarnFollowing, EncodeCrossCrate::No
1183 ),
1184 rustc_attr!(
1185 TEST, rustc_dump_user_args, Normal, template!(Word),
1186 WarnFollowing, EncodeCrossCrate::No
1187 ),
1188 rustc_attr!(
1189 TEST, rustc_evaluate_where_clauses, Normal, template!(Word), WarnFollowing,
1190 EncodeCrossCrate::Yes
1191 ),
1192 rustc_attr!(
1193 TEST, rustc_if_this_changed, Normal, template!(Word, List: "DepNode"), DuplicatesOk,
1194 EncodeCrossCrate::No
1195 ),
1196 rustc_attr!(
1197 TEST, rustc_then_this_would_need, Normal, template!(List: "DepNode"), DuplicatesOk,
1198 EncodeCrossCrate::No
1199 ),
1200 rustc_attr!(
1201 TEST, rustc_clean, Normal,
1202 template!(List: r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#),
1203 DuplicatesOk, EncodeCrossCrate::No
1204 ),
1205 rustc_attr!(
1206 TEST, rustc_partition_reused, Normal,
1207 template!(List: r#"cfg = "...", module = "...""#), DuplicatesOk, EncodeCrossCrate::No
1208 ),
1209 rustc_attr!(
1210 TEST, rustc_partition_codegened, Normal,
1211 template!(List: r#"cfg = "...", module = "...""#), DuplicatesOk, EncodeCrossCrate::No
1212 ),
1213 rustc_attr!(
1214 TEST, rustc_expected_cgu_reuse, Normal,
1215 template!(List: r#"cfg = "...", module = "...", kind = "...""#), DuplicatesOk,
1216 EncodeCrossCrate::No
1217 ),
1218 rustc_attr!(
1219 TEST, rustc_symbol_name, Normal, template!(Word),
1220 WarnFollowing, EncodeCrossCrate::No
1221 ),
1222 rustc_attr!(
1223 TEST, rustc_def_path, Normal, template!(Word),
1224 WarnFollowing, EncodeCrossCrate::No
1225 ),
1226 rustc_attr!(
1227 TEST, rustc_mir, Normal, template!(List: "arg1, arg2, ..."),
1228 DuplicatesOk, EncodeCrossCrate::Yes
1229 ),
1230 gated!(
1231 custom_mir, Normal, template!(List: r#"dialect = "...", phase = "...""#),
1232 ErrorFollowing, EncodeCrossCrate::No,
1233 "the `#[custom_mir]` attribute is just used for the Rust test suite",
1234 ),
1235 rustc_attr!(
1236 TEST, rustc_dump_item_bounds, Normal, template!(Word),
1237 WarnFollowing, EncodeCrossCrate::No
1238 ),
1239 rustc_attr!(
1240 TEST, rustc_dump_predicates, Normal, template!(Word),
1241 WarnFollowing, EncodeCrossCrate::No
1242 ),
1243 rustc_attr!(
1244 TEST, rustc_dump_def_parents, Normal, template!(Word),
1245 WarnFollowing, EncodeCrossCrate::No
1246 ),
1247 rustc_attr!(
1248 TEST, rustc_object_lifetime_default, Normal, template!(Word),
1249 WarnFollowing, EncodeCrossCrate::No
1250 ),
1251 rustc_attr!(
1252 TEST, rustc_dump_vtable, Normal, template!(Word),
1253 WarnFollowing, EncodeCrossCrate::No
1254 ),
1255 rustc_attr!(
1256 TEST, rustc_dummy, Normal, template!(Word ),
1257 DuplicatesOk, EncodeCrossCrate::No
1258 ),
1259 gated!(
1260 omit_gdb_pretty_printer_section, Normal, template!(Word),
1261 WarnFollowing, EncodeCrossCrate::No,
1262 "the `#[omit_gdb_pretty_printer_section]` attribute is just used for the Rust test suite",
1263 ),
1264 rustc_attr!(
1265 TEST, pattern_complexity_limit, CrateLevel, template!(NameValueStr: "N"),
1266 ErrorFollowing, EncodeCrossCrate::No,
1267 ),
1268];
1269
1270pub fn is_builtin_attr_name(name: Symbol) -> bool {
1271 BUILTIN_ATTRIBUTE_MAP.get(&name).is_some()
1272}
1273
1274pub fn encode_cross_crate(name: Symbol) -> bool {
1277 if let Some(attr) = BUILTIN_ATTRIBUTE_MAP.get(&name) {
1278 attr.encode_cross_crate == EncodeCrossCrate::Yes
1279 } else {
1280 true
1281 }
1282}
1283
1284pub fn is_valid_for_get_attr(name: Symbol) -> bool {
1285 BUILTIN_ATTRIBUTE_MAP.get(&name).is_some_and(|attr| match attr.duplicates {
1286 WarnFollowing | ErrorFollowing | ErrorPreceding | FutureWarnFollowing
1287 | FutureWarnPreceding => true,
1288 DuplicatesOk | WarnFollowingWordOnly => false,
1289 })
1290}
1291
1292pub static BUILTIN_ATTRIBUTE_MAP: LazyLock<FxHashMap<Symbol, &BuiltinAttribute>> =
1293 LazyLock::new(|| {
1294 let mut map = FxHashMap::default();
1295 for attr in BUILTIN_ATTRIBUTES.iter() {
1296 if map.insert(attr.name, attr).is_some() {
1297 panic!("duplicate builtin attribute `{}`", attr.name);
1298 }
1299 }
1300 map
1301 });
1302
1303pub fn is_stable_diagnostic_attribute(sym: Symbol, _features: &Features) -> bool {
1304 match sym {
1305 sym::on_unimplemented | sym::do_not_recommend => true,
1306 _ => false,
1307 }
1308}