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!(
618 const_trait, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No, const_trait_impl,
619 "`const_trait` is a temporary placeholder for marking a trait that is suitable for `const` \
620 `impls` and all default bodies as `const`, which may be removed or renamed in the \
621 future."
622 ),
623 gated!(
625 deprecated_safe, Normal, template!(List: r#"since = "version", note = "...""#), ErrorFollowing,
626 EncodeCrossCrate::Yes, experimental!(deprecated_safe),
627 ),
628
629 gated!(
631 cfi_encoding, Normal, template!(NameValueStr: "encoding"), ErrorPreceding,
632 EncodeCrossCrate::Yes, experimental!(cfi_encoding)
633 ),
634
635 gated!(
637 coroutine, Normal, template!(Word), ErrorFollowing,
638 EncodeCrossCrate::No, coroutines, experimental!(coroutine)
639 ),
640
641 gated!(
644 patchable_function_entry, Normal, template!(List: "prefix_nops = m, entry_nops = n"), ErrorPreceding,
645 EncodeCrossCrate::Yes, experimental!(patchable_function_entry)
646 ),
647
648 gated!(
651 type_const, Normal, template!(Word), ErrorFollowing,
652 EncodeCrossCrate::Yes, min_generic_const_args, experimental!(type_const),
653 ),
654
655 gated!(
660 const_continue, Normal, template!(Word), ErrorFollowing,
661 EncodeCrossCrate::No, loop_match, experimental!(const_continue)
662 ),
663 gated!(
664 loop_match, Normal, template!(Word), ErrorFollowing,
665 EncodeCrossCrate::No, loop_match, experimental!(loop_match)
666 ),
667
668 ungated!(
673 feature, CrateLevel,
674 template!(List: "name1, name2, ..."), DuplicatesOk, EncodeCrossCrate::No,
675 ),
676 ungated!(
678 stable, Normal,
679 template!(List: r#"feature = "name", since = "version""#), DuplicatesOk, EncodeCrossCrate::No,
680 ),
681 ungated!(
682 unstable, Normal,
683 template!(List: r#"feature = "name", reason = "...", issue = "N""#), DuplicatesOk,
684 EncodeCrossCrate::Yes
685 ),
686 ungated!(
687 rustc_const_unstable, Normal, template!(List: r#"feature = "name""#),
688 DuplicatesOk, EncodeCrossCrate::Yes
689 ),
690 ungated!(
691 rustc_const_stable, Normal,
692 template!(List: r#"feature = "name""#), DuplicatesOk, EncodeCrossCrate::No,
693 ),
694 ungated!(
695 rustc_default_body_unstable, Normal,
696 template!(List: r#"feature = "name", reason = "...", issue = "N""#),
697 DuplicatesOk, EncodeCrossCrate::No
698 ),
699 gated!(
700 allow_internal_unstable, Normal, template!(Word, List: "feat1, feat2, ..."),
701 DuplicatesOk, EncodeCrossCrate::Yes,
702 "allow_internal_unstable side-steps feature gating and stability checks",
703 ),
704 gated!(
705 allow_internal_unsafe, Normal, template!(Word), WarnFollowing,
706 EncodeCrossCrate::No, "allow_internal_unsafe side-steps the unsafe_code lint",
707 ),
708 rustc_attr!(
709 rustc_allowed_through_unstable_modules, Normal, template!(NameValueStr: "deprecation message"),
710 WarnFollowing, EncodeCrossCrate::No,
711 "rustc_allowed_through_unstable_modules special cases accidental stabilizations of stable items \
712 through unstable paths"
713 ),
714 rustc_attr!(
715 rustc_deprecated_safe_2024, Normal, template!(List: r#"audit_that = "...""#),
716 ErrorFollowing, EncodeCrossCrate::Yes,
717 "`#[rustc_deprecated_safe_2024]` is used to declare functions unsafe across the edition 2024 boundary",
718 ),
719 rustc_attr!(
720 rustc_pub_transparent, Normal, template!(Word),
721 ErrorFollowing, EncodeCrossCrate::Yes,
722 "used internally to mark types with a `transparent` representation when it is guaranteed by the documentation",
723 ),
724
725
726 gated!(fundamental, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes, experimental!(fundamental)),
731 gated!(
732 may_dangle, Normal, template!(Word), WarnFollowing,
733 EncodeCrossCrate::No, dropck_eyepatch,
734 "`may_dangle` has unstable semantics and may be removed in the future",
735 ),
736
737 rustc_attr!(
738 rustc_never_type_options,
739 Normal,
740 template!(List: r#"/*opt*/ fallback = "unit|niko|never|no""#),
741 ErrorFollowing,
742 EncodeCrossCrate::No,
743 "`rustc_never_type_options` is used to experiment with never type fallback and work on \
744 never type stabilization"
745 ),
746
747 rustc_attr!(
752 rustc_allocator, Normal, template!(Word), WarnFollowing,
753 EncodeCrossCrate::No,
754 ),
755 rustc_attr!(
756 rustc_nounwind, Normal, template!(Word), WarnFollowing,
757 EncodeCrossCrate::No,
758 ),
759 rustc_attr!(
760 rustc_reallocator, Normal, template!(Word), WarnFollowing,
761 EncodeCrossCrate::No,
762 ),
763 rustc_attr!(
764 rustc_deallocator, Normal, template!(Word), WarnFollowing,
765 EncodeCrossCrate::No,
766 ),
767 rustc_attr!(
768 rustc_allocator_zeroed, Normal, template!(Word), WarnFollowing,
769 EncodeCrossCrate::No,
770 ),
771 gated!(
772 default_lib_allocator, Normal, template!(Word), WarnFollowing,
773 EncodeCrossCrate::No, allocator_internals, experimental!(default_lib_allocator),
774 ),
775 gated!(
776 needs_allocator, Normal, template!(Word), WarnFollowing,
777 EncodeCrossCrate::No, allocator_internals, experimental!(needs_allocator),
778 ),
779 gated!(
780 panic_runtime, CrateLevel, template!(Word), WarnFollowing,
781 EncodeCrossCrate::No, experimental!(panic_runtime)
782 ),
783 gated!(
784 needs_panic_runtime, CrateLevel, template!(Word), WarnFollowing,
785 EncodeCrossCrate::No, experimental!(needs_panic_runtime)
786 ),
787 gated!(
788 compiler_builtins, CrateLevel, template!(Word), WarnFollowing,
789 EncodeCrossCrate::No,
790 "the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate \
791 which contains compiler-rt intrinsics and will never be stable",
792 ),
793 gated!(
794 profiler_runtime, CrateLevel, template!(Word), WarnFollowing,
795 EncodeCrossCrate::No,
796 "the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate \
797 which contains the profiler runtime and will never be stable",
798 ),
799
800 gated!(
805 linkage, Normal, template!(NameValueStr: "external|internal|..."),
806 ErrorPreceding, EncodeCrossCrate::No,
807 "the `linkage` attribute is experimental and not portable across platforms",
808 ),
809 rustc_attr!(
810 rustc_std_internal_symbol, Normal, template!(Word), WarnFollowing,
811 EncodeCrossCrate::No,
812 ),
813
814 rustc_attr!(
819 rustc_builtin_macro, Normal,
820 template!(Word, List: "name, /*opt*/ attributes(name1, name2, ...)"), ErrorFollowing,
821 EncodeCrossCrate::Yes,
822 ),
823 rustc_attr!(
824 rustc_proc_macro_decls, Normal, template!(Word), WarnFollowing,
825 EncodeCrossCrate::No,
826 ),
827 rustc_attr!(
828 rustc_macro_transparency, Normal,
829 template!(NameValueStr: "transparent|semiopaque|opaque"), ErrorFollowing,
830 EncodeCrossCrate::Yes, "used internally for testing macro hygiene",
831 ),
832 rustc_attr!(
833 rustc_autodiff, Normal,
834 template!(Word, List: r#""...""#), DuplicatesOk,
835 EncodeCrossCrate::Yes,
836 ),
837 ungated!(
842 cfg_trace, Normal, template!(Word ), DuplicatesOk,
843 EncodeCrossCrate::No
844 ),
845 ungated!(
846 cfg_attr_trace, Normal, template!(Word ), DuplicatesOk,
847 EncodeCrossCrate::No
848 ),
849
850 rustc_attr!(
855 rustc_on_unimplemented, Normal,
856 template!(
857 List: r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#,
858 NameValueStr: "message"
859 ),
860 ErrorFollowing, EncodeCrossCrate::Yes,
861 "see `#[diagnostic::on_unimplemented]` for the stable equivalent of this attribute"
862 ),
863 rustc_attr!(
864 rustc_confusables, Normal,
865 template!(List: r#""name1", "name2", ..."#),
866 ErrorFollowing, EncodeCrossCrate::Yes,
867 ),
868 rustc_attr!(
870 rustc_conversion_suggestion, Normal, template!(Word),
871 WarnFollowing, EncodeCrossCrate::Yes,
872 ),
873 rustc_attr!(
876 rustc_trivial_field_reads, Normal, template!(Word),
877 WarnFollowing, EncodeCrossCrate::Yes,
878 ),
879 rustc_attr!(
882 rustc_lint_query_instability, Normal, template!(Word),
883 WarnFollowing, EncodeCrossCrate::Yes,
884 ),
885 rustc_attr!(
888 rustc_lint_untracked_query_information, Normal, template!(Word),
889 WarnFollowing, EncodeCrossCrate::Yes,
890 ),
891 rustc_attr!(
894 rustc_lint_diagnostics, Normal, template!(Word),
895 WarnFollowing, EncodeCrossCrate::Yes,
896 ),
897 rustc_attr!(
900 rustc_lint_opt_ty, Normal, template!(Word),
901 WarnFollowing, EncodeCrossCrate::Yes,
902 ),
903 rustc_attr!(
906 rustc_lint_opt_deny_field_access, Normal, template!(List: "message"),
907 WarnFollowing, EncodeCrossCrate::Yes,
908 ),
909
910 rustc_attr!(
915 rustc_promotable, Normal, template!(Word), WarnFollowing,
916 EncodeCrossCrate::No, ),
917 rustc_attr!(
918 rustc_legacy_const_generics, Normal, template!(List: "N"), ErrorFollowing,
919 EncodeCrossCrate::Yes,
920 ),
921 rustc_attr!(
923 rustc_do_not_const_check, Normal, template!(Word), WarnFollowing,
924 EncodeCrossCrate::Yes, "`#[rustc_do_not_const_check]` skips const-check for this function's body",
925 ),
926 rustc_attr!(
927 rustc_const_panic_str, Normal, template!(Word), WarnFollowing,
928 EncodeCrossCrate::Yes, "`#[rustc_const_panic_str]` ensures the argument to this function is &&str during const-check",
929 ),
930 rustc_attr!(
931 rustc_const_stable_indirect, Normal,
932 template!(Word),
933 WarnFollowing,
934 EncodeCrossCrate::No,
935 "this is an internal implementation detail",
936 ),
937 rustc_attr!(
938 rustc_intrinsic_const_stable_indirect, Normal,
939 template!(Word), WarnFollowing, EncodeCrossCrate::No, "this is an internal implementation detail",
940 ),
941 gated!(
942 rustc_allow_const_fn_unstable, Normal,
943 template!(Word, List: "feat1, feat2, ..."), DuplicatesOk, EncodeCrossCrate::No,
944 "rustc_allow_const_fn_unstable side-steps feature gating and stability checks"
945 ),
946
947 rustc_attr!(
952 rustc_layout_scalar_valid_range_start, Normal, template!(List: "value"), ErrorFollowing,
953 EncodeCrossCrate::Yes,
954 "the `#[rustc_layout_scalar_valid_range_start]` attribute is just used to enable \
955 niche optimizations in the standard library",
956 ),
957 rustc_attr!(
958 rustc_layout_scalar_valid_range_end, Normal, template!(List: "value"), ErrorFollowing,
959 EncodeCrossCrate::Yes,
960 "the `#[rustc_layout_scalar_valid_range_end]` attribute is just used to enable \
961 niche optimizations in the standard library",
962 ),
963 rustc_attr!(
964 rustc_nonnull_optimization_guaranteed, Normal, template!(Word), WarnFollowing,
965 EncodeCrossCrate::Yes,
966 "the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to document \
967 guaranteed niche optimizations in the standard library",
968 "the compiler does not even check whether the type indeed is being non-null-optimized; \
969 it is your responsibility to ensure that the attribute is only used on types that are optimized",
970 ),
971
972 gated!(
976 lang, Normal, template!(NameValueStr: "name"), DuplicatesOk, EncodeCrossCrate::No, lang_items,
977 "lang items are subject to change",
978 ),
979 rustc_attr!(
980 rustc_as_ptr, Normal, template!(Word), ErrorFollowing,
981 EncodeCrossCrate::Yes,
982 "`#[rustc_as_ptr]` is used to mark functions returning pointers to their inner allocations."
983 ),
984 rustc_attr!(
985 rustc_pass_by_value, Normal, template!(Word), ErrorFollowing,
986 EncodeCrossCrate::Yes,
987 "`#[rustc_pass_by_value]` is used to mark types that must be passed by value instead of reference."
988 ),
989 rustc_attr!(
990 rustc_never_returns_null_ptr, Normal, template!(Word), ErrorFollowing,
991 EncodeCrossCrate::Yes,
992 "`#[rustc_never_returns_null_ptr]` is used to mark functions returning non-null pointers."
993 ),
994 rustc_attr!(
995 rustc_no_implicit_autorefs, AttributeType::Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes,
996 "`#[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."
997 ),
998 rustc_attr!(
999 rustc_coherence_is_core, AttributeType::CrateLevel, template!(Word), ErrorFollowing, EncodeCrossCrate::No,
1000 "`#![rustc_coherence_is_core]` allows inherent methods on builtin types, only intended to be used in `core`."
1001 ),
1002 rustc_attr!(
1003 rustc_coinductive, AttributeType::Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No,
1004 "`#[rustc_coinductive]` changes a trait to be coinductive, allowing cycles in the trait solver."
1005 ),
1006 rustc_attr!(
1007 rustc_allow_incoherent_impl, AttributeType::Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::No,
1008 "`#[rustc_allow_incoherent_impl]` has to be added to all impl items of an incoherent inherent impl."
1009 ),
1010 rustc_attr!(
1011 rustc_preserve_ub_checks, AttributeType::CrateLevel, template!(Word), ErrorFollowing, EncodeCrossCrate::No,
1012 "`#![rustc_preserve_ub_checks]` prevents the designated crate from evaluating whether UB checks are enabled when optimizing MIR",
1013 ),
1014 rustc_attr!(
1015 rustc_deny_explicit_impl,
1016 AttributeType::Normal,
1017 template!(Word),
1018 ErrorFollowing,
1019 EncodeCrossCrate::No,
1020 "`#[rustc_deny_explicit_impl]` enforces that a trait can have no user-provided impls"
1021 ),
1022 rustc_attr!(
1023 rustc_do_not_implement_via_object,
1024 AttributeType::Normal,
1025 template!(Word),
1026 ErrorFollowing,
1027 EncodeCrossCrate::No,
1028 "`#[rustc_do_not_implement_via_object]` opts out of the automatic trait impl for trait objects \
1029 (`impl Trait for dyn Trait`)"
1030 ),
1031 rustc_attr!(
1032 rustc_has_incoherent_inherent_impls, AttributeType::Normal, template!(Word),
1033 ErrorFollowing, EncodeCrossCrate::Yes,
1034 "`#[rustc_has_incoherent_inherent_impls]` allows the addition of incoherent inherent impls for \
1035 the given type by annotating all impl items with `#[rustc_allow_incoherent_impl]`."
1036 ),
1037
1038 BuiltinAttribute {
1039 name: sym::rustc_diagnostic_item,
1040 encode_cross_crate: EncodeCrossCrate::Yes,
1042 type_: Normal,
1043 safety: AttributeSafety::Normal,
1044 template: template!(NameValueStr: "name"),
1045 duplicates: ErrorFollowing,
1046 gate: Gated{
1047 feature: sym::rustc_attrs,
1048 message: "use of an internal attribute",
1049 check: Features::rustc_attrs,
1050 notes: &["the `#[rustc_diagnostic_item]` attribute allows the compiler to reference types \
1051 from the standard library for diagnostic purposes"],
1052 },
1053 },
1054 gated!(
1055 prelude_import, Normal, template!(Word), WarnFollowing,
1057 EncodeCrossCrate::No, "`#[prelude_import]` is for use by rustc only",
1058 ),
1059 gated!(
1060 rustc_paren_sugar, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No,
1061 unboxed_closures, "unboxed_closures are still evolving",
1062 ),
1063 rustc_attr!(
1064 rustc_inherit_overflow_checks, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No,
1065 "the `#[rustc_inherit_overflow_checks]` attribute is just used to control \
1066 overflow checking behavior of several functions in the standard library that are inlined \
1067 across crates",
1068 ),
1069 rustc_attr!(
1070 rustc_reservation_impl, Normal,
1071 template!(NameValueStr: "reservation message"), ErrorFollowing, EncodeCrossCrate::Yes,
1072 "the `#[rustc_reservation_impl]` attribute is internally used \
1073 for reserving `impl<T> From<!> for T` as part of the effort to stabilize `!`"
1074 ),
1075 rustc_attr!(
1076 rustc_test_marker, Normal, template!(NameValueStr: "name"), WarnFollowing,
1077 EncodeCrossCrate::No, "the `#[rustc_test_marker]` attribute is used internally to track tests",
1078 ),
1079 rustc_attr!(
1080 rustc_unsafe_specialization_marker, Normal, template!(Word),
1081 WarnFollowing, EncodeCrossCrate::No,
1082 "the `#[rustc_unsafe_specialization_marker]` attribute is used to check specializations"
1083 ),
1084 rustc_attr!(
1085 rustc_specialization_trait, Normal, template!(Word),
1086 WarnFollowing, EncodeCrossCrate::No,
1087 "the `#[rustc_specialization_trait]` attribute is used to check specializations"
1088 ),
1089 rustc_attr!(
1090 rustc_main, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No,
1091 "the `#[rustc_main]` attribute is used internally to specify test entry point function",
1092 ),
1093 rustc_attr!(
1094 rustc_skip_during_method_dispatch, Normal, template!(List: "array, boxed_slice"), ErrorFollowing,
1095 EncodeCrossCrate::No,
1096 "the `#[rustc_skip_during_method_dispatch]` attribute is used to exclude a trait \
1097 from method dispatch when the receiver is of the following type, for compatibility in \
1098 editions < 2021 (array) or editions < 2024 (boxed_slice)."
1099 ),
1100 rustc_attr!(
1101 rustc_must_implement_one_of, Normal, template!(List: "function1, function2, ..."),
1102 ErrorFollowing, EncodeCrossCrate::No,
1103 "the `#[rustc_must_implement_one_of]` attribute is used to change minimal complete \
1104 definition of a trait. Its syntax and semantics are highly experimental and will be \
1105 subject to change before stabilization",
1106 ),
1107 rustc_attr!(
1108 rustc_doc_primitive, Normal, template!(NameValueStr: "primitive name"), ErrorFollowing,
1109 EncodeCrossCrate::Yes, "the `#[rustc_doc_primitive]` attribute is used by the standard library \
1110 to provide a way to generate documentation for primitive types",
1111 ),
1112 gated!(
1113 rustc_intrinsic, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes, intrinsics,
1114 "the `#[rustc_intrinsic]` attribute is used to declare intrinsics as function items",
1115 ),
1116 rustc_attr!(
1117 rustc_no_mir_inline, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes,
1118 "`#[rustc_no_mir_inline]` prevents the MIR inliner from inlining a function while not affecting codegen"
1119 ),
1120 rustc_attr!(
1121 rustc_force_inline, Normal, template!(Word, NameValueStr: "reason"), WarnFollowing, EncodeCrossCrate::Yes,
1122 "`#[rustc_force_inline]` forces a free function to be inlined"
1123 ),
1124
1125 rustc_attr!(TEST, rustc_effective_visibility, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes),
1130 rustc_attr!(
1131 TEST, rustc_outlives, Normal, template!(Word),
1132 WarnFollowing, EncodeCrossCrate::No
1133 ),
1134 rustc_attr!(
1135 TEST, rustc_capture_analysis, Normal, template!(Word),
1136 WarnFollowing, EncodeCrossCrate::No
1137 ),
1138 rustc_attr!(
1139 TEST, rustc_insignificant_dtor, Normal, template!(Word),
1140 WarnFollowing, EncodeCrossCrate::Yes
1141 ),
1142 rustc_attr!(
1143 TEST, rustc_no_implicit_bounds, CrateLevel, template!(Word),
1144 WarnFollowing, EncodeCrossCrate::No
1145 ),
1146 rustc_attr!(
1147 TEST, rustc_strict_coherence, Normal, template!(Word),
1148 WarnFollowing, EncodeCrossCrate::Yes
1149 ),
1150 rustc_attr!(
1151 TEST, rustc_variance, Normal, template!(Word),
1152 WarnFollowing, EncodeCrossCrate::No
1153 ),
1154 rustc_attr!(
1155 TEST, rustc_variance_of_opaques, Normal, template!(Word),
1156 WarnFollowing, EncodeCrossCrate::No
1157 ),
1158 rustc_attr!(
1159 TEST, rustc_hidden_type_of_opaques, Normal, template!(Word),
1160 WarnFollowing, EncodeCrossCrate::No
1161 ),
1162 rustc_attr!(
1163 TEST, rustc_layout, Normal, template!(List: "field1, field2, ..."),
1164 WarnFollowing, EncodeCrossCrate::Yes
1165 ),
1166 rustc_attr!(
1167 TEST, rustc_abi, Normal, template!(List: "field1, field2, ..."),
1168 WarnFollowing, EncodeCrossCrate::No
1169 ),
1170 rustc_attr!(
1171 TEST, rustc_regions, Normal, template!(Word),
1172 WarnFollowing, EncodeCrossCrate::No
1173 ),
1174 rustc_attr!(
1175 TEST, rustc_delayed_bug_from_inside_query, Normal,
1176 template!(Word),
1177 WarnFollowing, EncodeCrossCrate::No
1178 ),
1179 rustc_attr!(
1180 TEST, rustc_dump_user_args, Normal, template!(Word),
1181 WarnFollowing, EncodeCrossCrate::No
1182 ),
1183 rustc_attr!(
1184 TEST, rustc_evaluate_where_clauses, Normal, template!(Word), WarnFollowing,
1185 EncodeCrossCrate::Yes
1186 ),
1187 rustc_attr!(
1188 TEST, rustc_if_this_changed, Normal, template!(Word, List: "DepNode"), DuplicatesOk,
1189 EncodeCrossCrate::No
1190 ),
1191 rustc_attr!(
1192 TEST, rustc_then_this_would_need, Normal, template!(List: "DepNode"), DuplicatesOk,
1193 EncodeCrossCrate::No
1194 ),
1195 rustc_attr!(
1196 TEST, rustc_clean, Normal,
1197 template!(List: r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#),
1198 DuplicatesOk, EncodeCrossCrate::No
1199 ),
1200 rustc_attr!(
1201 TEST, rustc_partition_reused, Normal,
1202 template!(List: r#"cfg = "...", module = "...""#), DuplicatesOk, EncodeCrossCrate::No
1203 ),
1204 rustc_attr!(
1205 TEST, rustc_partition_codegened, Normal,
1206 template!(List: r#"cfg = "...", module = "...""#), DuplicatesOk, EncodeCrossCrate::No
1207 ),
1208 rustc_attr!(
1209 TEST, rustc_expected_cgu_reuse, Normal,
1210 template!(List: r#"cfg = "...", module = "...", kind = "...""#), DuplicatesOk,
1211 EncodeCrossCrate::No
1212 ),
1213 rustc_attr!(
1214 TEST, rustc_symbol_name, Normal, template!(Word),
1215 WarnFollowing, EncodeCrossCrate::No
1216 ),
1217 rustc_attr!(
1218 TEST, rustc_def_path, Normal, template!(Word),
1219 WarnFollowing, EncodeCrossCrate::No
1220 ),
1221 rustc_attr!(
1222 TEST, rustc_mir, Normal, template!(List: "arg1, arg2, ..."),
1223 DuplicatesOk, EncodeCrossCrate::Yes
1224 ),
1225 gated!(
1226 custom_mir, Normal, template!(List: r#"dialect = "...", phase = "...""#),
1227 ErrorFollowing, EncodeCrossCrate::No,
1228 "the `#[custom_mir]` attribute is just used for the Rust test suite",
1229 ),
1230 rustc_attr!(
1231 TEST, rustc_dump_item_bounds, Normal, template!(Word),
1232 WarnFollowing, EncodeCrossCrate::No
1233 ),
1234 rustc_attr!(
1235 TEST, rustc_dump_predicates, Normal, template!(Word),
1236 WarnFollowing, EncodeCrossCrate::No
1237 ),
1238 rustc_attr!(
1239 TEST, rustc_dump_def_parents, Normal, template!(Word),
1240 WarnFollowing, EncodeCrossCrate::No
1241 ),
1242 rustc_attr!(
1243 TEST, rustc_object_lifetime_default, Normal, template!(Word),
1244 WarnFollowing, EncodeCrossCrate::No
1245 ),
1246 rustc_attr!(
1247 TEST, rustc_dump_vtable, Normal, template!(Word),
1248 WarnFollowing, EncodeCrossCrate::No
1249 ),
1250 rustc_attr!(
1251 TEST, rustc_dummy, Normal, template!(Word ),
1252 DuplicatesOk, EncodeCrossCrate::No
1253 ),
1254 gated!(
1255 omit_gdb_pretty_printer_section, Normal, template!(Word),
1256 WarnFollowing, EncodeCrossCrate::No,
1257 "the `#[omit_gdb_pretty_printer_section]` attribute is just used for the Rust test suite",
1258 ),
1259 rustc_attr!(
1260 TEST, pattern_complexity_limit, CrateLevel, template!(NameValueStr: "N"),
1261 ErrorFollowing, EncodeCrossCrate::No,
1262 ),
1263];
1264
1265pub fn is_builtin_attr_name(name: Symbol) -> bool {
1266 BUILTIN_ATTRIBUTE_MAP.get(&name).is_some()
1267}
1268
1269pub fn encode_cross_crate(name: Symbol) -> bool {
1272 if let Some(attr) = BUILTIN_ATTRIBUTE_MAP.get(&name) {
1273 attr.encode_cross_crate == EncodeCrossCrate::Yes
1274 } else {
1275 true
1276 }
1277}
1278
1279pub fn is_valid_for_get_attr(name: Symbol) -> bool {
1280 BUILTIN_ATTRIBUTE_MAP.get(&name).is_some_and(|attr| match attr.duplicates {
1281 WarnFollowing | ErrorFollowing | ErrorPreceding | FutureWarnFollowing
1282 | FutureWarnPreceding => true,
1283 DuplicatesOk | WarnFollowingWordOnly => false,
1284 })
1285}
1286
1287pub static BUILTIN_ATTRIBUTE_MAP: LazyLock<FxHashMap<Symbol, &BuiltinAttribute>> =
1288 LazyLock::new(|| {
1289 let mut map = FxHashMap::default();
1290 for attr in BUILTIN_ATTRIBUTES.iter() {
1291 if map.insert(attr.name, attr).is_some() {
1292 panic!("duplicate builtin attribute `{}`", attr.name);
1293 }
1294 }
1295 map
1296 });
1297
1298pub fn is_stable_diagnostic_attribute(sym: Symbol, _features: &Features) -> bool {
1299 match sym {
1300 sym::on_unimplemented | sym::do_not_recommend => true,
1301 _ => false,
1302 }
1303}