Skip to main content

rustc_feature/
builtin_attrs.rs

1//! Built-in attributes and `cfg` flag gating.
2
3use std::sync::LazyLock;
4
5use rustc_data_structures::fx::FxHashSet;
6use rustc_span::{Symbol, sym};
7
8use crate::Features;
9
10type GateFn = fn(&Features) -> bool;
11
12pub type GatedCfg = (Symbol, Symbol, GateFn);
13
14/// `cfg(...)`'s that are feature gated.
15const GATED_CFGS: &[GatedCfg] = &[
16    // (name in cfg, feature, function to check if the feature is enabled)
17    (sym::overflow_checks, sym::cfg_overflow_checks, Features::cfg_overflow_checks),
18    (sym::ub_checks, sym::cfg_ub_checks, Features::cfg_ub_checks),
19    (sym::contract_checks, sym::cfg_contract_checks, Features::cfg_contract_checks),
20    (sym::target_thread_local, sym::cfg_target_thread_local, Features::cfg_target_thread_local),
21    (
22        sym::target_has_atomic_load_store,
23        sym::cfg_target_has_atomic,
24        Features::cfg_target_has_atomic,
25    ),
26    (sym::sanitize, sym::cfg_sanitize, Features::cfg_sanitize),
27    (sym::version, sym::cfg_version, Features::cfg_version),
28    (sym::relocation_model, sym::cfg_relocation_model, Features::cfg_relocation_model),
29    (sym::sanitizer_cfi_generalize_pointers, sym::cfg_sanitizer_cfi, Features::cfg_sanitizer_cfi),
30    (sym::sanitizer_cfi_normalize_integers, sym::cfg_sanitizer_cfi, Features::cfg_sanitizer_cfi),
31    // this is consistent with naming of the compiler flag it's for
32    (sym::fmt_debug, sym::fmt_debug, Features::fmt_debug),
33    (
34        sym::target_has_reliable_f16,
35        sym::cfg_target_has_reliable_f16_f128,
36        Features::cfg_target_has_reliable_f16_f128,
37    ),
38    (
39        sym::target_has_reliable_f16_math,
40        sym::cfg_target_has_reliable_f16_f128,
41        Features::cfg_target_has_reliable_f16_f128,
42    ),
43    (
44        sym::target_has_reliable_f128,
45        sym::cfg_target_has_reliable_f16_f128,
46        Features::cfg_target_has_reliable_f16_f128,
47    ),
48    (
49        sym::target_has_reliable_f128_math,
50        sym::cfg_target_has_reliable_f16_f128,
51        Features::cfg_target_has_reliable_f16_f128,
52    ),
53    (sym::target_object_format, sym::cfg_target_object_format, Features::cfg_target_object_format),
54];
55
56/// Find a gated cfg determined by the `pred`icate which is given the cfg's name.
57pub fn find_gated_cfg(pred: impl Fn(Symbol) -> bool) -> Option<&'static GatedCfg> {
58    GATED_CFGS.iter().find(|(cfg_sym, ..)| pred(*cfg_sym))
59}
60
61#[derive(#[automatically_derived]
impl ::core::clone::Clone for AttributeStability {
    #[inline]
    fn clone(&self) -> AttributeStability {
        let _: ::core::clone::AssertParamIsClone<Symbol>;
        let _: ::core::clone::AssertParamIsClone<fn(&Features) -> bool>;
        let _: ::core::clone::AssertParamIsClone<&'static [&'static str]>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for AttributeStability {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            AttributeStability::Unstable {
                gate_name: __self_0, gate_check: __self_1, notes: __self_2 }
                =>
                ::core::fmt::Formatter::debug_struct_field3_finish(f,
                    "Unstable", "gate_name", __self_0, "gate_check", __self_1,
                    "notes", &__self_2),
            AttributeStability::Stable =>
                ::core::fmt::Formatter::write_str(f, "Stable"),
        }
    }
}Debug, #[automatically_derived]
impl ::core::marker::Copy for AttributeStability { }Copy)]
62pub enum AttributeStability {
63    /// An attribute that is unstable behind a specified feature fagte
64    Unstable {
65        /// The feature gate, for example `rustc_attrs` for rustc_* attributes.
66        gate_name: Symbol,
67        /// Check function to be called during the `PostExpansionVisitor` pass, which will be one of the `Features::*` functions
68        gate_check: fn(&Features) -> bool,
69        /// Notes to be displayed when an attempt is made to use the attribute without its feature gate.
70        notes: &'static [&'static str],
71    },
72    /// A stable attribute, can be used on all release channels
73    Stable,
74}
75
76/// Attributes that have a special meaning to rustc or rustdoc.
77#[rustfmt::skip]
78pub static BUILTIN_ATTRIBUTES: &[Symbol] = &[
79    // ==========================================================================
80    // Stable attributes:
81    // ==========================================================================
82
83    // Conditional compilation:
84    sym::cfg,
85    sym::cfg_attr,
86
87    // Testing:
88    sym::ignore,
89    sym::should_panic,
90
91    // Macros:
92    sym::automatically_derived,
93    sym::macro_use,
94    sym::macro_escape, // Deprecated synonym for `macro_use`.
95    sym::macro_export,
96    sym::proc_macro,
97    sym::proc_macro_derive,
98    sym::proc_macro_attribute,
99
100    // Lints:
101    sym::warn,
102    sym::allow,
103    sym::expect,
104    sym::forbid,
105    sym::deny,
106    sym::must_use,
107    sym::must_not_suspend,
108    sym::deprecated,
109
110    // Crate properties:
111    sym::crate_name,
112    sym::crate_type,
113
114    // ABI, linking, symbols, and FFI
115    sym::link,
116    sym::link_name,
117    sym::no_link,
118    sym::repr,
119    // FIXME(#82232, #143834): temporarily renamed to mitigate `#[align]` nameres ambiguity
120    sym::rustc_align,
121    sym::rustc_align_static,
122    sym::export_name,
123    sym::link_section,
124    sym::no_mangle,
125    sym::used,
126    sym::link_ordinal,
127    sym::naked,
128    // See `TyAndLayout::pass_indirectly_in_non_rustic_abis` for details.
129    sym::rustc_pass_indirectly_in_non_rustic_abis,
130
131    // Limits:
132    sym::recursion_limit,
133    sym::type_length_limit,
134    sym::move_size_limit,
135
136    // Entry point:
137    sym::no_main,
138
139    // Modules, prelude, and resolution:
140    sym::path,
141    sym::no_std,
142    sym::no_implicit_prelude,
143    sym::non_exhaustive,
144
145    // Runtime
146    sym::windows_subsystem,
147    sym::panic_handler, // RFC 2070
148
149    // Code generation:
150    sym::inline,
151    sym::cold,
152    sym::no_builtins,
153    sym::target_feature,
154    sym::track_caller,
155    sym::instruction_set,
156    sym::force_target_feature,
157    sym::sanitize,
158    sym::coverage,
159
160    sym::doc,
161
162    // Debugging
163    sym::debugger_visualizer,
164    sym::collapse_debuginfo,
165
166    // ==========================================================================
167    // Unstable attributes:
168    // ==========================================================================
169
170    // Linking:
171    sym::export_stable,
172
173    // Testing:
174    sym::test_runner,
175
176    sym::reexport_test_harness_main,
177
178    // RFC #1268
179    sym::marker,
180    sym::thread_local,
181    sym::no_core,
182    // RFC 2412
183    sym::optimize,
184
185    sym::ffi_pure,
186    sym::ffi_const,
187    sym::register_tool,
188    // `#[cfi_encoding = ""]`
189    sym::cfi_encoding,
190
191    // `#[coroutine]` attribute to be applied to closures to make them coroutines instead
192    sym::coroutine,
193
194    // RFC 3543
195    // `#[patchable_function_entry(prefix_nops = m, entry_nops = n)]`
196    sym::patchable_function_entry,
197
198    // The `#[loop_match]` and `#[const_continue]` attributes are part of the
199    // lang experiment for RFC 3720 tracked in:
200    //
201    // - https://github.com/rust-lang/rust/issues/132306
202    sym::const_continue,
203    sym::loop_match,
204
205    // The `#[pin_v2]` attribute is part of the `pin_ergonomics` experiment
206    // that allows structurally pinning, tracked in:
207    //
208    // - https://github.com/rust-lang/rust/issues/130494
209    sym::pin_v2,
210
211    // The `#[splat]` attribute is part of the `splat` experiment
212    // that improves the ergonomics of function overloading, tracked in:
213    //
214    // - https://github.com/rust-lang/rust/issues/153629
215    sym::splat,
216
217    // The `#[unroll]` attribute.
218    //
219    // - https://github.com/rust-lang/rust/pull/156816
220    sym::unroll,
221
222    // `#[instrument_fn = "on|off"]` to insert or inhibit instrumentation function
223    // calls inside a function, usually around the prologue.
224    //
225    // - https://github.com/rust-lang/rust/issues/157081
226    sym::instrument_fn,
227
228    // ==========================================================================
229    // Internal attributes: Stability, deprecation, and unsafe:
230    // ==========================================================================
231
232    sym::feature,
233    // DuplicatesOk since it has its own validation
234    sym::stable,
235    sym::unstable,
236    sym::unstable_feature_bound,
237    sym::unstable_removed,
238    sym::rustc_const_unstable,
239    sym::rustc_const_stable,
240    sym::rustc_default_body_unstable,
241    sym::allow_internal_unstable,
242    sym::allow_internal_unsafe,
243    sym::rustc_eii_foreign_item,
244    sym::rustc_allowed_through_unstable_modules,
245    sym::rustc_deprecated_safe_2024,
246    sym::rustc_pub_transparent,
247
248
249    // ==========================================================================
250    // Internal attributes: Type system related:
251    // ==========================================================================
252
253    sym::fundamental,
254    sym::may_dangle,
255
256    sym::rustc_never_type_options,
257
258    // ==========================================================================
259    // Internal attributes: Runtime related:
260    // ==========================================================================
261
262    sym::rustc_allocator,
263    sym::rustc_nounwind,
264    sym::rustc_reallocator,
265    sym::rustc_deallocator,
266    sym::rustc_allocator_zeroed,
267    sym::rustc_allocator_zeroed_variant,
268    sym::default_lib_allocator,
269    sym::needs_allocator,
270    sym::panic_runtime,
271    sym::needs_panic_runtime,
272    sym::compiler_builtins,
273    sym::profiler_runtime,
274
275    // ==========================================================================
276    // Internal attributes, Linkage:
277    // ==========================================================================
278
279    sym::linkage,
280    sym::rustc_std_internal_symbol,
281    sym::rustc_objc_class,
282    sym::rustc_objc_selector,
283
284    // ==========================================================================
285    // Internal attributes, Macro related:
286    // ==========================================================================
287
288    sym::rustc_builtin_macro,
289    sym::rustc_proc_macro_decls,
290    sym::rustc_macro_transparency,
291    sym::rustc_autodiff,
292    sym::rustc_offload_kernel,
293    // Traces that are left when `cfg` and `cfg_attr` attributes are expanded.
294    // The attributes are not gated, to avoid stability errors, but they cannot be used in stable
295    // or unstable code directly because `sym::cfg_(attr_)trace` are not valid identifiers, they
296    // can only be generated by the compiler.
297    sym::cfg_trace,
298    sym::cfg_attr_trace,
299
300    // ==========================================================================
301    // Internal attributes, Diagnostics related:
302    // ==========================================================================
303
304    sym::rustc_on_unimplemented,
305    sym::rustc_confusables,
306    // Enumerates "identity-like" conversion methods to suggest on type mismatch.
307    sym::rustc_conversion_suggestion,
308    // Prevents field reads in the marked trait or method to be considered
309    // during dead code analysis.
310    sym::rustc_trivial_field_reads,
311    // Used by the `rustc::potential_query_instability` lint to warn methods which
312    // might not be stable during incremental compilation.
313    sym::rustc_lint_query_instability,
314    // Used by the `rustc::untracked_query_information` lint to warn methods which
315    // might not be stable during incremental compilation.
316    sym::rustc_lint_untracked_query_information,
317    // Used by the `rustc::bad_opt_access` lint to identify `DebuggingOptions` and `CodegenOptions`
318    // types (as well as any others in future).
319    sym::rustc_lint_opt_ty,
320    // Used by the `rustc::bad_opt_access` lint on fields
321    // types (as well as any others in future).
322    sym::rustc_lint_opt_deny_field_access,
323
324    // ==========================================================================
325    // Internal attributes, Const related:
326    // ==========================================================================
327
328    sym::rustc_promotable,
329    sym::rustc_legacy_const_generics,
330    // Do not const-check this function's body. It will always get replaced during CTFE via `hook_special_const_fn`.
331    sym::rustc_do_not_const_check,
332    sym::rustc_const_stable_indirect,
333    sym::rustc_intrinsic_const_stable_indirect,
334    sym::rustc_allow_const_fn_unstable,
335
336    // ==========================================================================
337    // Internal attributes, Layout related:
338    // ==========================================================================
339
340    sym::rustc_simd_monomorphize_lane_limit,
341    sym::rustc_nonnull_optimization_guaranteed,
342
343    // ==========================================================================
344    // Internal attributes, Misc:
345    // ==========================================================================
346    sym::lang,
347    sym::rustc_as_ptr,
348    sym::rustc_should_not_be_called_on_const_items,
349    sym::rustc_pass_by_value,
350    sym::rustc_never_returns_null_ptr,
351    sym::rustc_no_implicit_autorefs,
352    sym::rustc_coherence_is_core,
353    sym::rustc_coinductive,
354    sym::rustc_comptime,
355    sym::rustc_allow_incoherent_impl,
356    sym::rustc_preserve_ub_checks,
357    sym::rustc_deny_explicit_impl,
358    sym::rustc_dyn_incompatible_trait,
359    sym::rustc_has_incoherent_inherent_impls,
360    sym::rustc_non_const_trait_method,
361
362    sym::rustc_diagnostic_item,
363    sym::prelude_import,
364    sym::rustc_paren_sugar,
365    sym::rustc_inherit_overflow_checks,
366    sym::rustc_reservation_impl,
367    sym::rustc_test_marker,
368    sym::rustc_unsafe_specialization_marker,
369    sym::rustc_specialization_trait,
370    sym::rustc_main,
371    sym::rustc_skip_during_method_dispatch,
372    sym::rustc_must_implement_one_of,
373    sym::rustc_doc_primitive,
374    sym::rustc_intrinsic,
375    sym::rustc_no_mir_inline,
376    sym::rustc_force_inline,
377    sym::rustc_scalable_vector,
378    sym::rustc_must_match_exhaustively,
379    sym::rustc_no_writable,
380
381    // ==========================================================================
382    // Internal attributes, Testing:
383    // ==========================================================================
384
385    sym::rustc_effective_visibility,
386    sym::rustc_dump_inferred_outlives,
387    sym::rustc_capture_analysis,
388    sym::rustc_insignificant_dtor,
389    sym::rustc_no_implicit_bounds,
390    sym::rustc_strict_coherence,
391    sym::rustc_dump_variances,
392    sym::rustc_dump_variances_of_opaques,
393    sym::rustc_dump_generics,
394    sym::rustc_dump_hidden_type_of_opaques,
395    sym::rustc_dump_layout,
396    sym::rustc_abi,
397    sym::rustc_regions,
398    sym::rustc_delayed_bug_from_inside_query,
399    sym::rustc_dump_user_args,
400    sym::rustc_evaluate_where_clauses,
401    sym::rustc_if_this_changed,
402    sym::rustc_then_this_would_need,
403    sym::rustc_clean,
404    sym::rustc_partition_reused,
405    sym::rustc_partition_codegened,
406    sym::rustc_expected_cgu_reuse,
407    sym::rustc_dump_symbol_name,
408    sym::rustc_dump_def_path,
409    sym::rustc_mir,
410    sym::custom_mir,
411    sym::rustc_dump_item_bounds,
412    sym::rustc_dump_predicates,
413    sym::rustc_dump_def_parents,
414    sym::rustc_dump_object_lifetime_defaults,
415    sym::rustc_dump_vtable,
416    sym::rustc_dummy,
417    sym::pattern_complexity_limit,
418];
419
420pub fn is_builtin_attr_name(name: Symbol) -> bool {
421    BUILTIN_ATTRIBUTE_MAP.get(&name).is_some()
422}
423
424pub static BUILTIN_ATTRIBUTE_MAP: LazyLock<FxHashSet<Symbol>> = LazyLock::new(|| {
425    let mut map = FxHashSet::default();
426    for attr in BUILTIN_ATTRIBUTES.iter() {
427        if !map.insert(*attr) {
428            {
    ::core::panicking::panic_fmt(format_args!("duplicate builtin attribute `{0}`",
            attr));
};panic!("duplicate builtin attribute `{}`", attr);
429        }
430    }
431    map
432});