| //! Built-in attributes and `cfg` flag gating. | |
| use std::sync::LazyLock; | |
| use rustc_data_structures::fx::FxHashSet; | |
| use rustc_span::{Symbol, sym}; | |
| use crate::Features; | |
| type GateFn = fn(&Features) -> bool; | |
| pub type GatedCfg = (Symbol, Symbol, GateFn); | |
| /// `cfg(...)`'s that are feature gated. | |
| const GATED_CFGS: &[GatedCfg] = &[ | |
| // (name in cfg, feature, function to check if the feature is enabled) | |
| (sym::overflow_checks, sym::cfg_overflow_checks, Features::cfg_overflow_checks), | |
| (sym::ub_checks, sym::cfg_ub_checks, Features::cfg_ub_checks), | |
| (sym::contract_checks, sym::cfg_contract_checks, Features::cfg_contract_checks), | |
| (sym::target_thread_local, sym::cfg_target_thread_local, Features::cfg_target_thread_local), | |
| ( | |
| sym::target_has_atomic_load_store, | |
| sym::cfg_target_has_atomic, | |
| Features::cfg_target_has_atomic, | |
| ), | |
| (sym::sanitize, sym::cfg_sanitize, Features::cfg_sanitize), | |
| (sym::version, sym::cfg_version, Features::cfg_version), | |
| (sym::relocation_model, sym::cfg_relocation_model, Features::cfg_relocation_model), | |
| (sym::sanitizer_cfi_generalize_pointers, sym::cfg_sanitizer_cfi, Features::cfg_sanitizer_cfi), | |
| (sym::sanitizer_cfi_normalize_integers, sym::cfg_sanitizer_cfi, Features::cfg_sanitizer_cfi), | |
| // this is consistent with naming of the compiler flag it's for | |
| (sym::fmt_debug, sym::fmt_debug, Features::fmt_debug), | |
| ( | |
| sym::target_has_reliable_f16, | |
| sym::cfg_target_has_reliable_f16_f128, | |
| Features::cfg_target_has_reliable_f16_f128, | |
| ), | |
| ( | |
| sym::target_has_reliable_f16_math, | |
| sym::cfg_target_has_reliable_f16_f128, | |
| Features::cfg_target_has_reliable_f16_f128, | |
| ), | |
| ( | |
| sym::target_has_reliable_f128, | |
| sym::cfg_target_has_reliable_f16_f128, | |
| Features::cfg_target_has_reliable_f16_f128, | |
| ), | |
| ( | |
| sym::target_has_reliable_f128_math, | |
| sym::cfg_target_has_reliable_f16_f128, | |
| Features::cfg_target_has_reliable_f16_f128, | |
| ), | |
| (sym::target_object_format, sym::cfg_target_object_format, Features::cfg_target_object_format), | |
| ]; | |
| /// Find a gated cfg determined by the `pred`icate which is given the cfg's name. | |
| pub fn find_gated_cfg(pred: impl Fn(Symbol) -> bool) -> Option<&'static GatedCfg> { | |
| GATED_CFGS.iter().find(|(cfg_sym, ..)| pred(*cfg_sym)) | |
| } | |
| #[derive(Clone, Debug, Copy)] | |
| pub enum AttributeStability { | |
| /// An attribute that is unstable behind a specified feature fagte | |
| Unstable { | |
| /// The feature gate, for example `rustc_attrs` for rustc_* attributes. | |
| gate_name: Symbol, | |
| /// Check function to be called during the `PostExpansionVisitor` pass, which will be one of the `Features::*` functions | |
| gate_check: fn(&Features) -> bool, | |
| /// Notes to be displayed when an attempt is made to use the attribute without its feature gate. | |
| notes: &'static [&'static str], | |
| }, | |
| /// A stable attribute, can be used on all release channels | |
| Stable, | |
| } | |
| /// Attributes that have a special meaning to rustc or rustdoc. | |
| #[rustfmt::skip] | |
| pub static BUILTIN_ATTRIBUTES: &[Symbol] = &[ | |
| // ========================================================================== | |
| // Stable attributes: | |
| // ========================================================================== | |
| // Conditional compilation: | |
| sym::cfg, | |
| sym::cfg_attr, | |
| // Testing: | |
| sym::ignore, | |
| sym::should_panic, | |
| // Macros: | |
| sym::automatically_derived, | |
| sym::macro_use, | |
| sym::macro_escape, // Deprecated synonym for `macro_use`. | |
| sym::macro_export, | |
| sym::proc_macro, | |
| sym::proc_macro_derive, | |
| sym::proc_macro_attribute, | |
| // Lints: | |
| sym::warn, | |
| sym::allow, | |
| sym::expect, | |
| sym::forbid, | |
| sym::deny, | |
| sym::must_use, | |
| sym::must_not_suspend, | |
| sym::deprecated, | |
| // Crate properties: | |
| sym::crate_name, | |
| sym::crate_type, | |
| // ABI, linking, symbols, and FFI | |
| sym::link, | |
| sym::link_name, | |
| sym::no_link, | |
| sym::repr, | |
| // FIXME(#82232, #143834): temporarily renamed to mitigate `#[align]` nameres ambiguity | |
| sym::rustc_align, | |
| sym::rustc_align_static, | |
| sym::export_name, | |
| sym::link_section, | |
| sym::no_mangle, | |
| sym::used, | |
| sym::link_ordinal, | |
| sym::naked, | |
| // See `TyAndLayout::pass_indirectly_in_non_rustic_abis` for details. | |
| sym::rustc_pass_indirectly_in_non_rustic_abis, | |
| // Limits: | |
| sym::recursion_limit, | |
| sym::type_length_limit, | |
| sym::move_size_limit, | |
| // Entry point: | |
| sym::no_main, | |
| // Modules, prelude, and resolution: | |
| sym::path, | |
| sym::no_std, | |
| sym::no_implicit_prelude, | |
| sym::non_exhaustive, | |
| // Runtime | |
| sym::windows_subsystem, | |
| sym::panic_handler, // RFC 2070 | |
| // Code generation: | |
| sym::inline, | |
| sym::cold, | |
| sym::no_builtins, | |
| sym::target_feature, | |
| sym::track_caller, | |
| sym::instruction_set, | |
| sym::force_target_feature, | |
| sym::sanitize, | |
| sym::coverage, | |
| sym::doc, | |
| // Debugging | |
| sym::debugger_visualizer, | |
| sym::collapse_debuginfo, | |
| // ========================================================================== | |
| // Unstable attributes: | |
| // ========================================================================== | |
| // Linking: | |
| sym::export_stable, | |
| // Testing: | |
| sym::test_runner, | |
| sym::reexport_test_harness_main, | |
| // RFC #1268 | |
| sym::marker, | |
| sym::thread_local, | |
| sym::no_core, | |
| // RFC 2412 | |
| sym::optimize, | |
| sym::ffi_pure, | |
| sym::ffi_const, | |
| sym::register_tool, | |
| // `#[cfi_encoding = ""]` | |
| sym::cfi_encoding, | |
| // `#[coroutine]` attribute to be applied to closures to make them coroutines instead | |
| sym::coroutine, | |
| // RFC 3543 | |
| // `#[patchable_function_entry(prefix_nops = m, entry_nops = n)]` | |
| sym::patchable_function_entry, | |
| // The `#[loop_match]` and `#[const_continue]` attributes are part of the | |
| // lang experiment for RFC 3720 tracked in: | |
| // | |
| // - https://github.com/rust-lang/rust/issues/132306 | |
| sym::const_continue, | |
| sym::loop_match, | |
| // The `#[pin_v2]` attribute is part of the `pin_ergonomics` experiment | |
| // that allows structurally pinning, tracked in: | |
| // | |
| // - https://github.com/rust-lang/rust/issues/130494 | |
| sym::pin_v2, | |
| // The `#[splat]` attribute is part of the `splat` experiment | |
| // that improves the ergonomics of function overloading, tracked in: | |
| // | |
| // - https://github.com/rust-lang/rust/issues/153629 | |
| sym::splat, | |
| // The `#[unroll]` attribute. | |
| // | |
| // - https://github.com/rust-lang/rust/pull/156816 | |
| sym::unroll, | |
| // `#[instrument_fn = "on|off"]` to insert or inhibit instrumentation function | |
| // calls inside a function, usually around the prologue. | |
| // | |
| // - https://github.com/rust-lang/rust/issues/157081 | |
| sym::instrument_fn, | |
| // ========================================================================== | |
| // Internal attributes: Stability, deprecation, and unsafe: | |
| // ========================================================================== | |
| sym::feature, | |
| // DuplicatesOk since it has its own validation | |
| sym::stable, | |
| sym::unstable, | |
| sym::unstable_feature_bound, | |
| sym::unstable_removed, | |
| sym::rustc_const_unstable, | |
| sym::rustc_const_stable, | |
| sym::rustc_default_body_unstable, | |
| sym::allow_internal_unstable, | |
| sym::allow_internal_unsafe, | |
| sym::rustc_eii_foreign_item, | |
| sym::rustc_allowed_through_unstable_modules, | |
| sym::rustc_deprecated_safe_2024, | |
| sym::rustc_pub_transparent, | |
| // ========================================================================== | |
| // Internal attributes: Type system related: | |
| // ========================================================================== | |
| sym::fundamental, | |
| sym::may_dangle, | |
| sym::rustc_never_type_options, | |
| // ========================================================================== | |
| // Internal attributes: Runtime related: | |
| // ========================================================================== | |
| sym::rustc_allocator, | |
| sym::rustc_nounwind, | |
| sym::rustc_reallocator, | |
| sym::rustc_deallocator, | |
| sym::rustc_allocator_zeroed, | |
| sym::rustc_allocator_zeroed_variant, | |
| sym::default_lib_allocator, | |
| sym::needs_allocator, | |
| sym::panic_runtime, | |
| sym::needs_panic_runtime, | |
| sym::compiler_builtins, | |
| sym::profiler_runtime, | |
| // ========================================================================== | |
| // Internal attributes, Linkage: | |
| // ========================================================================== | |
| sym::linkage, | |
| sym::rustc_std_internal_symbol, | |
| sym::rustc_objc_class, | |
| sym::rustc_objc_selector, | |
| // ========================================================================== | |
| // Internal attributes, Macro related: | |
| // ========================================================================== | |
| sym::rustc_builtin_macro, | |
| sym::rustc_proc_macro_decls, | |
| sym::rustc_macro_transparency, | |
| sym::rustc_autodiff, | |
| sym::rustc_offload_kernel, | |
| // Traces that are left when `cfg` and `cfg_attr` attributes are expanded. | |
| // The attributes are not gated, to avoid stability errors, but they cannot be used in stable | |
| // or unstable code directly because `sym::cfg_(attr_)trace` are not valid identifiers, they | |
| // can only be generated by the compiler. | |
| sym::cfg_trace, | |
| sym::cfg_attr_trace, | |
| // ========================================================================== | |
| // Internal attributes, Diagnostics related: | |
| // ========================================================================== | |
| sym::rustc_on_unimplemented, | |
| sym::rustc_confusables, | |
| // Enumerates "identity-like" conversion methods to suggest on type mismatch. | |
| sym::rustc_conversion_suggestion, | |
| // Prevents field reads in the marked trait or method to be considered | |
| // during dead code analysis. | |
| sym::rustc_trivial_field_reads, | |
| // Used by the `rustc::potential_query_instability` lint to warn methods which | |
| // might not be stable during incremental compilation. | |
| sym::rustc_lint_query_instability, | |
| // Used by the `rustc::untracked_query_information` lint to warn methods which | |
| // might not be stable during incremental compilation. | |
| sym::rustc_lint_untracked_query_information, | |
| // Used by the `rustc::bad_opt_access` lint to identify `DebuggingOptions` and `CodegenOptions` | |
| // types (as well as any others in future). | |
| sym::rustc_lint_opt_ty, | |
| // Used by the `rustc::bad_opt_access` lint on fields | |
| // types (as well as any others in future). | |
| sym::rustc_lint_opt_deny_field_access, | |
| // ========================================================================== | |
| // Internal attributes, Const related: | |
| // ========================================================================== | |
| sym::rustc_promotable, | |
| sym::rustc_legacy_const_generics, | |
| // Do not const-check this function's body. It will always get replaced during CTFE via `hook_special_const_fn`. | |
| sym::rustc_do_not_const_check, | |
| sym::rustc_const_stable_indirect, | |
| sym::rustc_intrinsic_const_stable_indirect, | |
| sym::rustc_allow_const_fn_unstable, | |
| // ========================================================================== | |
| // Internal attributes, Layout related: | |
| // ========================================================================== | |
| sym::rustc_simd_monomorphize_lane_limit, | |
| sym::rustc_nonnull_optimization_guaranteed, | |
| // ========================================================================== | |
| // Internal attributes, Misc: | |
| // ========================================================================== | |
| sym::lang, | |
| sym::rustc_as_ptr, | |
| sym::rustc_should_not_be_called_on_const_items, | |
| sym::rustc_pass_by_value, | |
| sym::rustc_never_returns_null_ptr, | |
| sym::rustc_no_implicit_autorefs, | |
| sym::rustc_coherence_is_core, | |
| sym::rustc_coinductive, | |
| sym::rustc_comptime, | |
| sym::rustc_allow_incoherent_impl, | |
| sym::rustc_preserve_ub_checks, | |
| sym::rustc_deny_explicit_impl, | |
| sym::rustc_dyn_incompatible_trait, | |
| sym::rustc_has_incoherent_inherent_impls, | |
| sym::rustc_non_const_trait_method, | |
| sym::rustc_diagnostic_item, | |
| sym::prelude_import, | |
| sym::rustc_paren_sugar, | |
| sym::rustc_inherit_overflow_checks, | |
| sym::rustc_reservation_impl, | |
| sym::rustc_test_marker, | |
| sym::rustc_unsafe_specialization_marker, | |
| sym::rustc_specialization_trait, | |
| sym::rustc_main, | |
| sym::rustc_skip_during_method_dispatch, | |
| sym::rustc_must_implement_one_of, | |
| sym::rustc_doc_primitive, | |
| sym::rustc_intrinsic, | |
| sym::rustc_no_mir_inline, | |
| sym::rustc_force_inline, | |
| sym::rustc_scalable_vector, | |
| sym::rustc_must_match_exhaustively, | |
| sym::rustc_no_writable, | |
| // ========================================================================== | |
| // Internal attributes, Testing: | |
| // ========================================================================== | |
| sym::rustc_effective_visibility, | |
| sym::rustc_dump_inferred_outlives, | |
| sym::rustc_capture_analysis, | |
| sym::rustc_insignificant_dtor, | |
| sym::rustc_no_implicit_bounds, | |
| sym::rustc_strict_coherence, | |
| sym::rustc_dump_variances, | |
| sym::rustc_dump_variances_of_opaques, | |
| sym::rustc_dump_generics, | |
| sym::rustc_dump_hidden_type_of_opaques, | |
| sym::rustc_dump_layout, | |
| sym::rustc_abi, | |
| sym::rustc_regions, | |
| sym::rustc_delayed_bug_from_inside_query, | |
| sym::rustc_dump_user_args, | |
| sym::rustc_evaluate_where_clauses, | |
| sym::rustc_if_this_changed, | |
| sym::rustc_then_this_would_need, | |
| sym::rustc_clean, | |
| sym::rustc_partition_reused, | |
| sym::rustc_partition_codegened, | |
| sym::rustc_expected_cgu_reuse, | |
| sym::rustc_dump_symbol_name, | |
| sym::rustc_dump_def_path, | |
| sym::rustc_mir, | |
| sym::custom_mir, | |
| sym::rustc_dump_item_bounds, | |
| sym::rustc_dump_predicates, | |
| sym::rustc_dump_def_parents, | |
| sym::rustc_dump_object_lifetime_defaults, | |
| sym::rustc_dump_vtable, | |
| sym::rustc_dummy, | |
| sym::pattern_complexity_limit, | |
| ]; | |
| pub fn is_builtin_attr_name(name: Symbol) -> bool { | |
| BUILTIN_ATTRIBUTE_MAP.get(&name).is_some() | |
| } | |
| pub static BUILTIN_ATTRIBUTE_MAP: LazyLock<FxHashSet<Symbol>> = LazyLock::new(|| { | |
| let mut map = FxHashSet::default(); | |
| for attr in BUILTIN_ATTRIBUTES.iter() { | |
| if !map.insert(*attr) { | |
| panic!("duplicate builtin attribute `{}`", attr); | |
| } | |
| } | |
| map | |
| }); |