summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_feature
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /compiler/rustc_feature
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_feature')
-rw-r--r--compiler/rustc_feature/Cargo.toml11
-rw-r--r--compiler/rustc_feature/src/accepted.rs344
-rw-r--r--compiler/rustc_feature/src/active.rs552
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs833
-rw-r--r--compiler/rustc_feature/src/lib.rs155
-rw-r--r--compiler/rustc_feature/src/removed.rs203
-rw-r--r--compiler/rustc_feature/src/tests.rs23
7 files changed, 2121 insertions, 0 deletions
diff --git a/compiler/rustc_feature/Cargo.toml b/compiler/rustc_feature/Cargo.toml
new file mode 100644
index 000000000..3d8d0db20
--- /dev/null
+++ b/compiler/rustc_feature/Cargo.toml
@@ -0,0 +1,11 @@
+[package]
+name = "rustc_feature"
+version = "0.0.0"
+edition = "2021"
+
+[lib]
+doctest = false
+
+[dependencies]
+rustc_data_structures = { path = "../rustc_data_structures" }
+rustc_span = { path = "../rustc_span" }
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
new file mode 100644
index 000000000..099c40b21
--- /dev/null
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -0,0 +1,344 @@
+//! List of the accepted feature gates.
+
+use super::{to_nonzero, Feature, State};
+use rustc_span::symbol::sym;
+
+macro_rules! declare_features {
+ ($(
+ $(#[doc = $doc:tt])* (accepted, $feature:ident, $ver:expr, $issue:expr, None),
+ )+) => {
+ /// Those language feature has since been Accepted (it was once Active)
+ pub const ACCEPTED_FEATURES: &[Feature] = &[
+ $(
+ Feature {
+ state: State::Accepted,
+ name: sym::$feature,
+ since: $ver,
+ issue: to_nonzero($issue),
+ edition: None,
+ }
+ ),+
+ ];
+ }
+}
+
+#[rustfmt::skip]
+declare_features! (
+ // -------------------------------------------------------------------------
+ // feature-group-start: for testing purposes
+ // -------------------------------------------------------------------------
+
+ /// A temporary feature gate used to enable parser extensions needed
+ /// to bootstrap fix for #5723.
+ (accepted, issue_5723_bootstrap, "1.0.0", None, None),
+ /// These are used to test this portion of the compiler,
+ /// they don't actually mean anything.
+ (accepted, test_accepted_feature, "1.0.0", None, None),
+ // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!
+ // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way.
+ // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!
+
+ // -------------------------------------------------------------------------
+ // feature-group-end: for testing purposes
+ // -------------------------------------------------------------------------
+
+ // -------------------------------------------------------------------------
+ // feature-group-start: accepted features
+ // -------------------------------------------------------------------------
+
+ /// Allows `#[target_feature(...)]` on aarch64 platforms
+ (accepted, aarch64_target_feature, "1.61.0", Some(44839), None),
+ /// Allows the sysV64 ABI to be specified on all platforms
+ /// instead of just the platforms on which it is the C ABI.
+ (accepted, abi_sysv64, "1.24.0", Some(36167), None),
+ /// Allows using ADX intrinsics from `core::arch::{x86, x86_64}`.
+ (accepted, adx_target_feature, "1.61.0", Some(44839), None),
+ /// Allows the definition of associated constants in `trait` or `impl` blocks.
+ (accepted, associated_consts, "1.20.0", Some(29646), None),
+ /// Allows using associated `type`s in `trait`s.
+ (accepted, associated_types, "1.0.0", None, None),
+ /// Allows free and inherent `async fn`s, `async` blocks, and `<expr>.await` expressions.
+ (accepted, async_await, "1.39.0", Some(50547), None),
+ /// Allows all literals in attribute lists and values of key-value pairs.
+ (accepted, attr_literals, "1.30.0", Some(34981), None),
+ /// Allows overloading augmented assignment operations like `a += b`.
+ (accepted, augmented_assignments, "1.8.0", Some(28235), None),
+ /// Allows mixing bind-by-move in patterns and references to those identifiers in guards.
+ (accepted, bind_by_move_pattern_guards, "1.39.0", Some(15287), None),
+ /// Allows bindings in the subpattern of a binding pattern.
+ /// For example, you can write `x @ Some(y)`.
+ (accepted, bindings_after_at, "1.56.0", Some(65490), None),
+ /// Allows empty structs and enum variants with braces.
+ (accepted, braced_empty_structs, "1.8.0", Some(29720), None),
+ /// Allows `#[cfg_attr(predicate, multiple, attributes, here)]`.
+ (accepted, cfg_attr_multi, "1.33.0", Some(54881), None),
+ /// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests.
+ (accepted, cfg_doctest, "1.40.0", Some(62210), None),
+ /// Enables `#[cfg(panic = "...")]` config key.
+ (accepted, cfg_panic, "1.60.0", Some(77443), None),
+ /// Allows `cfg(target_feature = "...")`.
+ (accepted, cfg_target_feature, "1.27.0", Some(29717), None),
+ /// Allows `cfg(target_vendor = "...")`.
+ (accepted, cfg_target_vendor, "1.33.0", Some(29718), None),
+ /// Allows implementing `Clone` for closures where possible (RFC 2132).
+ (accepted, clone_closures, "1.26.0", Some(44490), None),
+ /// Allows coercing non capturing closures to function pointers.
+ (accepted, closure_to_fn_coercion, "1.19.0", Some(39817), None),
+ /// Allows usage of the `compile_error!` macro.
+ (accepted, compile_error, "1.20.0", Some(40872), None),
+ /// Allows `impl Trait` in function return types.
+ (accepted, conservative_impl_trait, "1.26.0", Some(34511), None),
+ /// Allows calling constructor functions in `const fn`.
+ (accepted, const_constructor, "1.40.0", Some(61456), None),
+ /// Allows using and casting function pointers in a `const fn`.
+ (accepted, const_fn_fn_ptr_basics, "1.61.0", Some(57563), None),
+ /// Allows trait bounds in `const fn`.
+ (accepted, const_fn_trait_bound, "1.61.0", Some(93706), None),
+ /// Allows calling `transmute` in const fn
+ (accepted, const_fn_transmute, "1.56.0", Some(53605), None),
+ /// Allows accessing fields of unions inside `const` functions.
+ (accepted, const_fn_union, "1.56.0", Some(51909), None),
+ /// Allows unsizing coercions in `const fn`.
+ (accepted, const_fn_unsize, "1.54.0", Some(64992), None),
+ /// Allows const generics to have default values (e.g. `struct Foo<const N: usize = 3>(...);`).
+ (accepted, const_generics_defaults, "1.59.0", Some(44580), None),
+ /// Allows the use of `if` and `match` in constants.
+ (accepted, const_if_match, "1.46.0", Some(49146), None),
+ /// Allows argument and return position `impl Trait` in a `const fn`.
+ (accepted, const_impl_trait, "1.61.0", Some(77463), None),
+ /// Allows indexing into constant arrays.
+ (accepted, const_indexing, "1.26.0", Some(29947), None),
+ /// Allows let bindings, assignments and destructuring in `const` functions and constants.
+ /// As long as control flow is not implemented in const eval, `&&` and `||` may not be used
+ /// at the same time as let bindings.
+ (accepted, const_let, "1.33.0", Some(48821), None),
+ /// Allows the use of `loop` and `while` in constants.
+ (accepted, const_loop, "1.46.0", Some(52000), None),
+ /// Allows panicking during const eval (producing compile-time errors).
+ (accepted, const_panic, "1.57.0", Some(51999), None),
+ /// Allows dereferencing raw pointers during const eval.
+ (accepted, const_raw_ptr_deref, "1.58.0", Some(51911), None),
+ /// Allows implementing `Copy` for closures where possible (RFC 2132).
+ (accepted, copy_closures, "1.26.0", Some(44490), None),
+ /// Allows `crate` in paths.
+ (accepted, crate_in_paths, "1.30.0", Some(45477), None),
+ /// Allows using assigning a default type to type parameters in algebraic data type definitions.
+ (accepted, default_type_params, "1.0.0", None, None),
+ /// Allows `#[deprecated]` attribute.
+ (accepted, deprecated, "1.9.0", Some(29935), None),
+ /// Allows `#[derive(Default)]` and `#[default]` on enums.
+ (accepted, derive_default_enum, "1.62.0", Some(86985), None),
+ /// Allows the use of destructuring assignments.
+ (accepted, destructuring_assignment, "1.59.0", Some(71126), None),
+ /// Allows `#[doc(alias = "...")]`.
+ (accepted, doc_alias, "1.48.0", Some(50146), None),
+ /// Allows `..` in tuple (struct) patterns.
+ (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627), None),
+ /// Allows `..=` in patterns (RFC 1192).
+ (accepted, dotdoteq_in_patterns, "1.26.0", Some(28237), None),
+ /// Allows `Drop` types in constants (RFC 1440).
+ (accepted, drop_types_in_const, "1.22.0", Some(33156), None),
+ /// Allows using `dyn Trait` as a syntax for trait objects.
+ (accepted, dyn_trait, "1.27.0", Some(44662), None),
+ /// Allows integer match exhaustiveness checking (RFC 2591).
+ (accepted, exhaustive_integer_patterns, "1.33.0", Some(50907), None),
+ /// Allows explicit generic arguments specification with `impl Trait` present.
+ (accepted, explicit_generic_args_with_impl_trait, "1.63.0", Some(83701), None),
+ /// Allows arbitrary expressions in key-value attributes at parse time.
+ (accepted, extended_key_value_attributes, "1.54.0", Some(78835), None),
+ /// Allows resolving absolute paths as paths from other crates.
+ (accepted, extern_absolute_paths, "1.30.0", Some(44660), None),
+ /// Allows `extern crate foo as bar;`. This puts `bar` into extern prelude.
+ (accepted, extern_crate_item_prelude, "1.31.0", Some(55599), None),
+ /// Allows `extern crate self as foo;`.
+ /// This puts local crate root into extern prelude under name `foo`.
+ (accepted, extern_crate_self, "1.34.0", Some(56409), None),
+ /// Allows access to crate names passed via `--extern` through prelude.
+ (accepted, extern_prelude, "1.30.0", Some(44660), None),
+ /// Allows field shorthands (`x` meaning `x: x`) in struct literal expressions.
+ (accepted, field_init_shorthand, "1.17.0", Some(37340), None),
+ /// Allows `#[must_use]` on functions, and introduces must-use operators (RFC 1940).
+ (accepted, fn_must_use, "1.27.0", Some(43302), None),
+ /// Allows capturing variables in scope using format_args!
+ (accepted, format_args_capture, "1.58.0", Some(67984), None),
+ /// Allows attributes on lifetime/type formal parameters in generics (RFC 1327).
+ (accepted, generic_param_attrs, "1.27.0", Some(48848), None),
+ /// Allows the `#[global_allocator]` attribute.
+ (accepted, global_allocator, "1.28.0", Some(27389), None),
+ // FIXME: explain `globs`.
+ (accepted, globs, "1.0.0", None, None),
+ /// Allows using the `u128` and `i128` types.
+ (accepted, i128_type, "1.26.0", Some(35118), None),
+ /// Allows the use of `if let` expressions.
+ (accepted, if_let, "1.0.0", None, None),
+ /// Allows top level or-patterns (`p | q`) in `if let` and `while let`.
+ (accepted, if_while_or_patterns, "1.33.0", Some(48215), None),
+ /// Allows lifetime elision in `impl` headers. For example:
+ /// + `impl<I:Iterator> Iterator for &mut Iterator`
+ /// + `impl Debug for Foo<'_>`
+ (accepted, impl_header_lifetime_elision, "1.31.0", Some(15872), None),
+ /// Allows using `a..=b` and `..=b` as inclusive range syntaxes.
+ (accepted, inclusive_range_syntax, "1.26.0", Some(28237), None),
+ /// Allows inferring outlives requirements (RFC 2093).
+ (accepted, infer_outlives_requirements, "1.30.0", Some(44493), None),
+ /// Allows irrefutable patterns in `if let` and `while let` statements (RFC 2086).
+ (accepted, irrefutable_let_patterns, "1.33.0", Some(44495), None),
+ /// Allows some increased flexibility in the name resolution rules,
+ /// especially around globs and shadowing (RFC 1560).
+ (accepted, item_like_imports, "1.15.0", Some(35120), None),
+ /// Allows `break {expr}` with a value inside `loop`s.
+ (accepted, loop_break_value, "1.19.0", Some(37339), None),
+ /// Allows use of `?` as the Kleene "at most one" operator in macros.
+ (accepted, macro_at_most_once_rep, "1.32.0", Some(48075), None),
+ /// Allows macro attributes to observe output of `#[derive]`.
+ (accepted, macro_attributes_in_derive_output, "1.57.0", Some(81119), None),
+ /// Allows use of the `:lifetime` macro fragment specifier.
+ (accepted, macro_lifetime_matcher, "1.27.0", Some(34303), None),
+ /// Allows use of the `:literal` macro fragment specifier (RFC 1576).
+ (accepted, macro_literal_matcher, "1.32.0", Some(35625), None),
+ /// Allows `macro_rules!` items.
+ (accepted, macro_rules, "1.0.0", None, None),
+ /// Allows use of the `:vis` macro fragment specifier
+ (accepted, macro_vis_matcher, "1.30.0", Some(41022), None),
+ /// Allows macro invocations in `extern {}` blocks.
+ (accepted, macros_in_extern, "1.40.0", Some(49476), None),
+ /// Allows '|' at beginning of match arms (RFC 1925).
+ (accepted, match_beginning_vert, "1.25.0", Some(44101), None),
+ /// Allows default match binding modes (RFC 2005).
+ (accepted, match_default_bindings, "1.26.0", Some(42640), None),
+ /// Allows `impl Trait` with multiple unrelated lifetimes.
+ (accepted, member_constraints, "1.54.0", Some(61997), None),
+ /// Allows the definition of `const fn` functions.
+ (accepted, min_const_fn, "1.31.0", Some(53555), None),
+ /// The smallest useful subset of const generics.
+ (accepted, min_const_generics, "1.51.0", Some(74878), None),
+ /// Allows calling `const unsafe fn` inside `unsafe` blocks in `const fn` functions.
+ (accepted, min_const_unsafe_fn, "1.33.0", Some(55607), None),
+ /// Allows using `Self` and associated types in struct expressions and patterns.
+ (accepted, more_struct_aliases, "1.16.0", Some(37544), None),
+ /// Allows patterns with concurrent by-move and by-ref bindings.
+ /// For example, you can write `Foo(a, ref b)` where `a` is by-move and `b` is by-ref.
+ (accepted, move_ref_pattern, "1.49.0", Some(68354), None),
+ /// Allows specifying modifiers in the link attribute: `#[link(modifiers = "...")]`
+ (accepted, native_link_modifiers, "1.61.0", Some(81490), None),
+ /// Allows specifying the bundle link modifier
+ (accepted, native_link_modifiers_bundle, "1.63.0", Some(81490), None),
+ /// Allows specifying the whole-archive link modifier
+ (accepted, native_link_modifiers_whole_archive, "1.61.0", Some(81490), None),
+ /// Allows using non lexical lifetimes (RFC 2094).
+ (accepted, nll, "1.63.0", Some(43234), None),
+ /// Allows using `#![no_std]`.
+ (accepted, no_std, "1.6.0", None, None),
+ /// Allows defining identifiers beyond ASCII.
+ (accepted, non_ascii_idents, "1.53.0", Some(55467), None),
+ /// Allows future-proofing enums/structs with the `#[non_exhaustive]` attribute (RFC 2008).
+ (accepted, non_exhaustive, "1.40.0", Some(44109), None),
+ /// Allows `foo.rs` as an alternative to `foo/mod.rs`.
+ (accepted, non_modrs_mods, "1.30.0", Some(44660), None),
+ /// Allows the use of or-patterns (e.g., `0 | 1`).
+ (accepted, or_patterns, "1.53.0", Some(54883), None),
+ /// Allows annotating functions conforming to `fn(&PanicInfo) -> !` with `#[panic_handler]`.
+ /// This defines the behavior of panics.
+ (accepted, panic_handler, "1.30.0", Some(44489), None),
+ /// Allows attributes in formal function parameters.
+ (accepted, param_attrs, "1.39.0", Some(60406), None),
+ /// Allows parentheses in patterns.
+ (accepted, pattern_parentheses, "1.31.0", Some(51087), None),
+ /// Allows procedural macros in `proc-macro` crates.
+ (accepted, proc_macro, "1.29.0", Some(38356), None),
+ /// Allows multi-segment paths in attributes and derives.
+ (accepted, proc_macro_path_invoc, "1.30.0", Some(38356), None),
+ /// Allows `pub(restricted)` visibilities (RFC 1422).
+ (accepted, pub_restricted, "1.18.0", Some(32409), None),
+ /// Allows use of the postfix `?` operator in expressions.
+ (accepted, question_mark, "1.13.0", Some(31436), None),
+ /// Allows keywords to be escaped for use as identifiers.
+ (accepted, raw_identifiers, "1.30.0", Some(48589), None),
+ /// Allows relaxing the coherence rules such that
+ /// `impl<T> ForeignTrait<LocalType> for ForeignType<T>` is permitted.
+ (accepted, re_rebalance_coherence, "1.41.0", Some(55437), None),
+ /// Allows numeric fields in struct expressions and patterns.
+ (accepted, relaxed_adts, "1.19.0", Some(35626), None),
+ /// Lessens the requirements for structs to implement `Unsize`.
+ (accepted, relaxed_struct_unsize, "1.58.0", Some(81793), None),
+ /// Allows `repr(align(16))` struct attribute (RFC 1358).
+ (accepted, repr_align, "1.25.0", Some(33626), None),
+ /// Allows using `#[repr(align(X))]` on enums with equivalent semantics
+ /// to wrapping an enum in a wrapper struct with `#[repr(align(X))]`.
+ (accepted, repr_align_enum, "1.37.0", Some(57996), None),
+ /// Allows `#[repr(packed(N))]` attribute on structs.
+ (accepted, repr_packed, "1.33.0", Some(33158), None),
+ /// Allows `#[repr(transparent)]` attribute on newtype structs.
+ (accepted, repr_transparent, "1.28.0", Some(43036), None),
+ /// Allows code like `let x: &'static u32 = &42` to work (RFC 1414).
+ (accepted, rvalue_static_promotion, "1.21.0", Some(38865), None),
+ /// Allows `Self` in type definitions (RFC 2300).
+ (accepted, self_in_typedefs, "1.32.0", Some(49303), None),
+ /// Allows `Self` struct constructor (RFC 2302).
+ (accepted, self_struct_ctor, "1.32.0", Some(51994), None),
+ /// Allows using subslice patterns, `[a, .., b]` and `[a, xs @ .., b]`.
+ (accepted, slice_patterns, "1.42.0", Some(62254), None),
+ /// Allows use of `&foo[a..b]` as a slicing syntax.
+ (accepted, slicing_syntax, "1.0.0", None, None),
+ /// Allows elision of `'static` lifetimes in `static`s and `const`s.
+ (accepted, static_in_const, "1.17.0", Some(35897), None),
+ /// Allows the definition recursive static items.
+ (accepted, static_recursion, "1.17.0", Some(29719), None),
+ /// Allows attributes on struct literal fields.
+ (accepted, struct_field_attributes, "1.20.0", Some(38814), None),
+ /// Allows struct variants `Foo { baz: u8, .. }` in enums (RFC 418).
+ (accepted, struct_variant, "1.0.0", None, None),
+ /// Allows `#[target_feature(...)]`.
+ (accepted, target_feature, "1.27.0", None, None),
+ /// Allows `fn main()` with return types which implements `Termination` (RFC 1937).
+ (accepted, termination_trait, "1.26.0", Some(43301), None),
+ /// Allows `#[test]` functions where the return type implements `Termination` (RFC 1937).
+ (accepted, termination_trait_test, "1.27.0", Some(48854), None),
+ /// Allows attributes scoped to tools.
+ (accepted, tool_attributes, "1.30.0", Some(44690), None),
+ /// Allows scoped lints.
+ (accepted, tool_lints, "1.31.0", Some(44690), None),
+ /// Allows `#[track_caller]` to be used which provides
+ /// accurate caller location reporting during panic (RFC 2091).
+ (accepted, track_caller, "1.46.0", Some(47809), None),
+ /// Allows #[repr(transparent)] on univariant enums (RFC 2645).
+ (accepted, transparent_enums, "1.42.0", Some(60405), None),
+ /// Allows indexing tuples.
+ (accepted, tuple_indexing, "1.0.0", None, None),
+ /// Allows paths to enum variants on type aliases including `Self`.
+ (accepted, type_alias_enum_variants, "1.37.0", Some(49683), None),
+ /// Allows macros to appear in the type position.
+ (accepted, type_macros, "1.13.0", Some(27245), None),
+ /// Allows `const _: TYPE = VALUE`.
+ (accepted, underscore_const_names, "1.37.0", Some(54912), None),
+ /// Allows `use path as _;` and `extern crate c as _;`.
+ (accepted, underscore_imports, "1.33.0", Some(48216), None),
+ /// Allows `'_` placeholder lifetimes.
+ (accepted, underscore_lifetimes, "1.26.0", Some(44524), None),
+ /// Allows `use x::y;` to search `x` in the current scope.
+ (accepted, uniform_paths, "1.32.0", Some(53130), None),
+ /// Allows `impl Trait` in function arguments.
+ (accepted, universal_impl_trait, "1.26.0", Some(34511), None),
+ /// Allows arbitrary delimited token streams in non-macro attributes.
+ (accepted, unrestricted_attribute_tokens, "1.34.0", Some(55208), None),
+ /// The `unsafe_op_in_unsafe_fn` lint (allowed by default): no longer treat an unsafe function as an unsafe block.
+ (accepted, unsafe_block_in_unsafe_fn, "1.52.0", Some(71668), None),
+ /// Allows importing and reexporting macros with `use`,
+ /// enables macro modularization in general.
+ (accepted, use_extern_macros, "1.30.0", Some(35896), None),
+ /// Allows nested groups in `use` items (RFC 2128).
+ (accepted, use_nested_groups, "1.25.0", Some(44494), None),
+ /// Allows `#[used]` to preserve symbols (see llvm.compiler.used).
+ (accepted, used, "1.30.0", Some(40289), None),
+ /// Allows the use of `while let` expressions.
+ (accepted, while_let, "1.0.0", None, None),
+ /// Allows `#![windows_subsystem]`.
+ (accepted, windows_subsystem, "1.18.0", Some(37499), None),
+ // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!
+ // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way.
+ // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!
+
+ // -------------------------------------------------------------------------
+ // feature-group-end: accepted features
+ // -------------------------------------------------------------------------
+);
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
new file mode 100644
index 000000000..ef4a17564
--- /dev/null
+++ b/compiler/rustc_feature/src/active.rs
@@ -0,0 +1,552 @@
+//! List of the active feature gates.
+
+use super::{to_nonzero, Feature, State};
+
+use rustc_data_structures::fx::FxHashSet;
+use rustc_span::edition::Edition;
+use rustc_span::symbol::{sym, Symbol};
+use rustc_span::Span;
+
+macro_rules! set {
+ ($field: ident) => {{
+ fn f(features: &mut Features, _: Span) {
+ features.$field = true;
+ }
+ f as fn(&mut Features, Span)
+ }};
+}
+
+macro_rules! declare_features {
+ (__status_to_bool active) => {
+ false
+ };
+ (__status_to_bool incomplete) => {
+ true
+ };
+ ($(
+ $(#[doc = $doc:tt])* ($status:ident, $feature:ident, $ver:expr, $issue:expr, $edition:expr),
+ )+) => {
+ /// Represents active features that are currently being implemented or
+ /// currently being considered for addition/removal.
+ pub const ACTIVE_FEATURES:
+ &[Feature] =
+ &[$(
+ // (sym::$feature, $ver, $issue, $edition, set!($feature))
+ Feature {
+ state: State::Active { set: set!($feature) },
+ name: sym::$feature,
+ since: $ver,
+ issue: to_nonzero($issue),
+ edition: $edition,
+ }
+ ),+];
+
+ /// A set of features to be used by later passes.
+ #[derive(Clone, Default, Debug)]
+ pub struct Features {
+ /// `#![feature]` attrs for language features, for error reporting.
+ pub declared_lang_features: Vec<(Symbol, Span, Option<Symbol>)>,
+ /// `#![feature]` attrs for non-language (library) features.
+ pub declared_lib_features: Vec<(Symbol, Span)>,
+ /// Features enabled for this crate.
+ pub active_features: FxHashSet<Symbol>,
+ $(
+ $(#[doc = $doc])*
+ pub $feature: bool
+ ),+
+ }
+
+ impl Features {
+ pub fn walk_feature_fields(&self, mut f: impl FnMut(&str, bool)) {
+ $(f(stringify!($feature), self.$feature);)+
+ }
+
+ /// Is the given feature active?
+ pub fn active(&self, feature: Symbol) -> bool {
+ self.active_features.contains(&feature)
+ }
+
+ /// Is the given feature enabled?
+ ///
+ /// Panics if the symbol doesn't correspond to a declared feature.
+ pub fn enabled(&self, feature: Symbol) -> bool {
+ match feature {
+ $( sym::$feature => self.$feature, )*
+
+ _ => panic!("`{}` was not listed in `declare_features`", feature),
+ }
+ }
+
+ /// Some features are known to be incomplete and using them is likely to have
+ /// unanticipated results, such as compiler crashes. We warn the user about these
+ /// to alert them.
+ pub fn incomplete(&self, feature: Symbol) -> bool {
+ match feature {
+ $(
+ sym::$feature => declare_features!(__status_to_bool $status),
+ )*
+ // accepted and removed features aren't in this file but are never incomplete
+ _ if self.declared_lang_features.iter().any(|f| f.0 == feature) => false,
+ _ if self.declared_lib_features.iter().any(|f| f.0 == feature) => false,
+ _ => panic!("`{}` was not listed in `declare_features`", feature),
+ }
+ }
+ }
+ };
+}
+
+impl Feature {
+ /// Sets this feature in `Features`. Panics if called on a non-active feature.
+ pub fn set(&self, features: &mut Features, span: Span) {
+ match self.state {
+ State::Active { set } => set(features, span),
+ _ => panic!("called `set` on feature `{}` which is not `active`", self.name),
+ }
+ }
+}
+
+// See https://rustc-dev-guide.rust-lang.org/feature-gates.html#feature-gates for more
+// documentation about handling feature gates.
+//
+// If you change this, please modify `src/doc/unstable-book` as well.
+//
+// Don't ever remove anything from this list; move them to `accepted.rs` if
+// accepted or `removed.rs` if removed.
+//
+// The version numbers here correspond to the version in which the current status
+// was set. This is most important for knowing when a particular feature became
+// stable (active).
+//
+// Note that the features are grouped into internal/user-facing and then
+// sorted by version inside those groups. This is enforced with tidy.
+//
+// N.B., `tools/tidy/src/features.rs` parses this information directly out of the
+// source, so take care when modifying it.
+
+#[rustfmt::skip]
+declare_features! (
+ // -------------------------------------------------------------------------
+ // feature-group-start: internal feature gates (no tracking issue)
+ // -------------------------------------------------------------------------
+ // no-tracking-issue-start
+
+ /// Allows using the `thiscall` ABI.
+ (active, abi_thiscall, "1.19.0", None, None),
+ /// Allows using the `unadjusted` ABI; perma-unstable.
+ (active, abi_unadjusted, "1.16.0", None, None),
+ /// Allows using the `vectorcall` ABI.
+ (active, abi_vectorcall, "1.7.0", None, None),
+ /// Allows using `#![needs_allocator]`, an implementation detail of `#[global_allocator]`.
+ (active, allocator_internals, "1.20.0", None, None),
+ /// Allows using `#[allow_internal_unsafe]`. This is an
+ /// attribute on `macro_rules!` and can't use the attribute handling
+ /// below (it has to be checked before expansion possibly makes
+ /// macros disappear).
+ (active, allow_internal_unsafe, "1.0.0", None, None),
+ /// Allows using `#[allow_internal_unstable]`. This is an
+ /// attribute on `macro_rules!` and can't use the attribute handling
+ /// below (it has to be checked before expansion possibly makes
+ /// macros disappear).
+ (active, allow_internal_unstable, "1.0.0", None, None),
+ /// Allows using anonymous lifetimes in argument-position impl-trait.
+ (active, anonymous_lifetime_in_impl_trait, "1.63.0", None, None),
+ /// Allows identifying the `compiler_builtins` crate.
+ (active, compiler_builtins, "1.13.0", None, None),
+ /// Outputs useful `assert!` messages
+ (active, generic_assert, "1.63.0", None, None),
+ /// Allows using the `rust-intrinsic`'s "ABI".
+ (active, intrinsics, "1.0.0", None, None),
+ /// Allows using `#[lang = ".."]` attribute for linking items to special compiler logic.
+ (active, lang_items, "1.0.0", None, None),
+ /// Allows using `#[omit_gdb_pretty_printer_section]`.
+ (active, omit_gdb_pretty_printer_section, "1.5.0", None, None),
+ /// Allows using `#[prelude_import]` on glob `use` items.
+ (active, prelude_import, "1.2.0", None, None),
+ /// Used to identify crates that contain the profiler runtime.
+ (active, profiler_runtime, "1.18.0", None, None),
+ /// Allows using `rustc_*` attributes (RFC 572).
+ (active, rustc_attrs, "1.0.0", None, None),
+ /// Allows using the `#[stable]` and `#[unstable]` attributes.
+ (active, staged_api, "1.0.0", None, None),
+ /// Added for testing E0705; perma-unstable.
+ (active, test_2018_feature, "1.31.0", None, Some(Edition::Edition2018)),
+ /// Added for testing unstable lints; perma-unstable.
+ (active, test_unstable_lint, "1.60.0", None, None),
+ /// Allows non-`unsafe` —and thus, unsound— access to `Pin` constructions.
+ /// Marked `incomplete` since perma-unstable and unsound.
+ (incomplete, unsafe_pin_internals, "1.60.0", None, None),
+ /// Use for stable + negative coherence and strict coherence depending on trait's
+ /// rustc_strict_coherence value.
+ (active, with_negative_coherence, "1.60.0", None, None),
+ // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!
+ // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way.
+ // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!
+
+ // no-tracking-issue-end
+ // -------------------------------------------------------------------------
+ // feature-group-end: internal feature gates (no tracking issue)
+ // -------------------------------------------------------------------------
+
+ // -------------------------------------------------------------------------
+ // feature-group-start: internal feature gates
+ // -------------------------------------------------------------------------
+
+ /// Allows features specific to auto traits.
+ /// Renamed from `optin_builtin_traits`.
+ (active, auto_traits, "1.50.0", Some(13231), None),
+ /// Allows using `box` in patterns (RFC 469).
+ (active, box_patterns, "1.0.0", Some(29641), None),
+ /// Allows using the `box $expr` syntax.
+ (active, box_syntax, "1.0.0", Some(49733), None),
+ /// Allows `#[doc(notable_trait)]`.
+ /// Renamed from `doc_spotlight`.
+ (active, doc_notable_trait, "1.52.0", Some(45040), None),
+ /// Allows using the `may_dangle` attribute (RFC 1327).
+ (active, dropck_eyepatch, "1.10.0", Some(34761), None),
+ /// Allows using the `#[fundamental]` attribute.
+ (active, fundamental, "1.0.0", Some(29635), None),
+ /// Allows using `#[link_name="llvm.*"]`.
+ (active, link_llvm_intrinsics, "1.0.0", Some(29602), None),
+ /// Allows using the `#[linkage = ".."]` attribute.
+ (active, linkage, "1.0.0", Some(29603), None),
+ /// Allows declaring with `#![needs_panic_runtime]` that a panic runtime is needed.
+ (active, needs_panic_runtime, "1.10.0", Some(32837), None),
+ /// Allows using the `#![panic_runtime]` attribute.
+ (active, panic_runtime, "1.10.0", Some(32837), None),
+ /// Allows using `#[rustc_allow_const_fn_unstable]`.
+ /// This is an attribute on `const fn` for the same
+ /// purpose as `#[allow_internal_unstable]`.
+ (active, rustc_allow_const_fn_unstable, "1.49.0", Some(69399), None),
+ /// Allows using compiler's own crates.
+ (active, rustc_private, "1.0.0", Some(27812), None),
+ /// Allows using internal rustdoc features like `doc(primitive)` or `doc(keyword)`.
+ (active, rustdoc_internals, "1.58.0", Some(90418), None),
+ /// Allows using `#[start]` on a function indicating that it is the program entrypoint.
+ (active, start, "1.0.0", Some(29633), None),
+ /// Allows using `#[structural_match]` which indicates that a type is structurally matchable.
+ /// FIXME: Subsumed by trait `StructuralPartialEq`, cannot move to removed until a library
+ /// feature with the same name exists.
+ (active, structural_match, "1.8.0", Some(31434), None),
+ /// Allows using the `rust-call` ABI.
+ (active, unboxed_closures, "1.0.0", Some(29625), None),
+ // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!
+ // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way.
+ // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!
+
+ // -------------------------------------------------------------------------
+ // feature-group-end: internal feature gates
+ // -------------------------------------------------------------------------
+
+ // -------------------------------------------------------------------------
+ // feature-group-start: actual feature gates (target features)
+ // -------------------------------------------------------------------------
+
+ // FIXME: Document these and merge with the list below.
+
+ // Unstable `#[target_feature]` directives.
+ (active, aarch64_ver_target_feature, "1.27.0", Some(44839), None),
+ (active, arm_target_feature, "1.27.0", Some(44839), None),
+ (active, avx512_target_feature, "1.27.0", Some(44839), None),
+ (active, bpf_target_feature, "1.54.0", Some(44839), None),
+ (active, cmpxchg16b_target_feature, "1.32.0", Some(44839), None),
+ (active, ermsb_target_feature, "1.49.0", Some(44839), None),
+ (active, f16c_target_feature, "1.36.0", Some(44839), None),
+ (active, hexagon_target_feature, "1.27.0", Some(44839), None),
+ (active, mips_target_feature, "1.27.0", Some(44839), None),
+ (active, movbe_target_feature, "1.34.0", Some(44839), None),
+ (active, powerpc_target_feature, "1.27.0", Some(44839), None),
+ (active, riscv_target_feature, "1.45.0", Some(44839), None),
+ (active, rtm_target_feature, "1.35.0", Some(44839), None),
+ (active, sse4a_target_feature, "1.27.0", Some(44839), None),
+ (active, tbm_target_feature, "1.27.0", Some(44839), None),
+ (active, wasm_target_feature, "1.30.0", Some(44839), None),
+ // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!
+ // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way.
+ // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!
+
+ // -------------------------------------------------------------------------
+ // feature-group-end: actual feature gates (target features)
+ // -------------------------------------------------------------------------
+
+ // -------------------------------------------------------------------------
+ // feature-group-start: actual feature gates
+ // -------------------------------------------------------------------------
+
+ /// Allows using the `amdgpu-kernel` ABI.
+ (active, abi_amdgpu_kernel, "1.29.0", Some(51575), None),
+ /// Allows `extern "avr-interrupt" fn()` and `extern "avr-non-blocking-interrupt" fn()`.
+ (active, abi_avr_interrupt, "1.45.0", Some(69664), None),
+ /// Allows `extern "C-cmse-nonsecure-call" fn()`.
+ (active, abi_c_cmse_nonsecure_call, "1.51.0", Some(81391), None),
+ /// Allows using the `efiapi` ABI.
+ (active, abi_efiapi, "1.40.0", Some(65815), None),
+ /// Allows `extern "msp430-interrupt" fn()`.
+ (active, abi_msp430_interrupt, "1.16.0", Some(38487), None),
+ /// Allows `extern "ptx-*" fn()`.
+ (active, abi_ptx, "1.15.0", Some(38788), None),
+ /// Allows `extern "x86-interrupt" fn()`.
+ (active, abi_x86_interrupt, "1.17.0", Some(40180), None),
+ /// Allows additional const parameter types, such as `&'static str` or user defined types
+ (incomplete, adt_const_params, "1.56.0", Some(95174), None),
+ /// Allows defining an `#[alloc_error_handler]`.
+ (active, alloc_error_handler, "1.29.0", Some(51540), None),
+ /// Allows explicit discriminants on non-unit enum variants.
+ (active, arbitrary_enum_discriminant, "1.37.0", Some(60553), None),
+ /// Allows trait methods with arbitrary self types.
+ (active, arbitrary_self_types, "1.23.0", Some(44874), None),
+ /// Allows using `const` operands in inline assembly.
+ (active, asm_const, "1.58.0", Some(93332), None),
+ /// Enables experimental inline assembly support for additional architectures.
+ (active, asm_experimental_arch, "1.58.0", Some(93335), None),
+ /// Allows using `sym` operands in inline assembly.
+ (active, asm_sym, "1.58.0", Some(93333), None),
+ /// Allows the `may_unwind` option in inline assembly.
+ (active, asm_unwind, "1.58.0", Some(93334), None),
+ /// Allows users to enforce equality of associated constants `TraitImpl<AssocConst=3>`.
+ (active, associated_const_equality, "1.58.0", Some(92827), None),
+ /// Allows the user of associated type bounds.
+ (active, associated_type_bounds, "1.34.0", Some(52662), None),
+ /// Allows associated type defaults.
+ (active, associated_type_defaults, "1.2.0", Some(29661), None),
+ /// Allows `async || body` closures.
+ (active, async_closure, "1.37.0", Some(62290), None),
+ /// Allows `extern "C-unwind" fn` to enable unwinding across ABI boundaries.
+ (active, c_unwind, "1.52.0", Some(74990), None),
+ /// Allows using C-variadics.
+ (active, c_variadic, "1.34.0", Some(44930), None),
+ /// Allows capturing disjoint fields in a closure/generator (RFC 2229).
+ (incomplete, capture_disjoint_fields, "1.49.0", Some(53488), None),
+ /// Allows the use of `#[cfg(sanitize = "option")]`; set when -Zsanitizer is used.
+ (active, cfg_sanitize, "1.41.0", Some(39699), None),
+ /// Allows `cfg(target_abi = "...")`.
+ (active, cfg_target_abi, "1.55.0", Some(80970), None),
+ /// Allows `cfg(target(abi = "..."))`.
+ (active, cfg_target_compact, "1.63.0", Some(96901), None),
+ /// Allows `cfg(target_has_atomic_load_store = "...")`.
+ (active, cfg_target_has_atomic, "1.60.0", Some(94039), None),
+ /// Allows `cfg(target_has_atomic_equal_alignment = "...")`.
+ (active, cfg_target_has_atomic_equal_alignment, "1.60.0", Some(93822), None),
+ /// Allows `cfg(target_thread_local)`.
+ (active, cfg_target_thread_local, "1.7.0", Some(29594), None),
+ /// Allow conditional compilation depending on rust version
+ (active, cfg_version, "1.45.0", Some(64796), None),
+ /// Allows `for<...>` on closures and generators.
+ (active, closure_lifetime_binder, "1.64.0", Some(97362), None),
+ /// Allows `#[track_caller]` on closures and generators.
+ (active, closure_track_caller, "1.57.0", Some(87417), None),
+ /// Allows to use the `#[cmse_nonsecure_entry]` attribute.
+ (active, cmse_nonsecure_entry, "1.48.0", Some(75835), None),
+ /// Allows `async {}` expressions in const contexts.
+ (active, const_async_blocks, "1.53.0", Some(85368), None),
+ // Allows limiting the evaluation steps of const expressions
+ (active, const_eval_limit, "1.43.0", Some(67217), None),
+ /// Allows the definition of `const extern fn` and `const unsafe extern fn`.
+ (active, const_extern_fn, "1.40.0", Some(64926), None),
+ /// Allows basic arithmetic on floating point types in a `const fn`.
+ (active, const_fn_floating_point_arithmetic, "1.48.0", Some(57241), None),
+ /// Allows `for _ in _` loops in const contexts.
+ (active, const_for, "1.56.0", Some(87575), None),
+ /// Allows using `&mut` in constant functions.
+ (active, const_mut_refs, "1.41.0", Some(57349), None),
+ /// Be more precise when looking for live drops in a const context.
+ (active, const_precise_live_drops, "1.46.0", Some(73255), None),
+ /// Allows references to types with interior mutability within constants
+ (active, const_refs_to_cell, "1.51.0", Some(80384), None),
+ /// Allows `impl const Trait for T` syntax.
+ (active, const_trait_impl, "1.42.0", Some(67792), None),
+ /// Allows the `?` operator in const contexts.
+ (active, const_try, "1.56.0", Some(74935), None),
+ /// Allows non-builtin attributes in inner attribute position.
+ (active, custom_inner_attributes, "1.30.0", Some(54726), None),
+ /// Allows custom test frameworks with `#![test_runner]` and `#[test_case]`.
+ (active, custom_test_frameworks, "1.30.0", Some(50297), None),
+ /// Allows using `#[debugger_visualizer]`.
+ (active, debugger_visualizer, "1.62.0", Some(95939), None),
+ /// Allows declarative macros 2.0 (`macro`).
+ (active, decl_macro, "1.17.0", Some(39412), None),
+ /// Allows rustc to inject a default alloc_error_handler
+ (active, default_alloc_error_handler, "1.48.0", Some(66741), None),
+ /// Allows default type parameters to influence type inference.
+ (active, default_type_parameter_fallback, "1.3.0", Some(27336), None),
+ /// Allows using `#[deprecated_safe]` to deprecate the safeness of a function or trait
+ (active, deprecated_safe, "1.61.0", Some(94978), None),
+ /// Allows having using `suggestion` in the `#[deprecated]` attribute.
+ (active, deprecated_suggestion, "1.61.0", Some(94785), None),
+ /// Tells rustdoc to automatically generate `#[doc(cfg(...))]`.
+ (active, doc_auto_cfg, "1.58.0", Some(43781), None),
+ /// Allows `#[doc(cfg(...))]`.
+ (active, doc_cfg, "1.21.0", Some(43781), None),
+ /// Allows `#[doc(cfg_hide(...))]`.
+ (active, doc_cfg_hide, "1.57.0", Some(43781), None),
+ /// Allows `#[doc(masked)]`.
+ (active, doc_masked, "1.21.0", Some(44027), None),
+ /// Allows `X..Y` patterns.
+ (active, exclusive_range_pattern, "1.11.0", Some(37854), None),
+ /// Allows exhaustive pattern matching on types that contain uninhabited types.
+ (active, exhaustive_patterns, "1.13.0", Some(51085), None),
+ /// Allows defining `extern type`s.
+ (active, extern_types, "1.23.0", Some(43467), None),
+ /// Allows the use of `#[ffi_const]` on foreign functions.
+ (active, ffi_const, "1.45.0", Some(58328), None),
+ /// Allows the use of `#[ffi_pure]` on foreign functions.
+ (active, ffi_pure, "1.45.0", Some(58329), None),
+ /// Allows using `#[ffi_returns_twice]` on foreign functions.
+ (active, ffi_returns_twice, "1.34.0", Some(58314), None),
+ /// Allows using `#[repr(align(...))]` on function items
+ (active, fn_align, "1.53.0", Some(82232), None),
+ /// Allows defining generators.
+ (active, generators, "1.21.0", Some(43122), None),
+ /// Infer generic args for both consts and types.
+ (active, generic_arg_infer, "1.55.0", Some(85077), None),
+ /// Allows associated types to be generic, e.g., `type Foo<T>;` (RFC 1598).
+ (active, generic_associated_types, "1.23.0", Some(44265), None),
+ /// An extension to the `generic_associated_types` feature, allowing incomplete features.
+ (incomplete, generic_associated_types_extended, "1.61.0", Some(95451), None),
+ /// Allows non-trivial generic constants which have to have wfness manually propagated to callers
+ (incomplete, generic_const_exprs, "1.56.0", Some(76560), None),
+ /// Allows using `..X`, `..=X`, `...X`, and `X..` as a pattern.
+ (active, half_open_range_patterns, "1.41.0", Some(67264), None),
+ /// Allows `if let` guard in match arms.
+ (active, if_let_guard, "1.47.0", Some(51114), None),
+ /// Allows using imported `main` function
+ (active, imported_main, "1.53.0", Some(28937), None),
+ /// Allows associated types in inherent impls.
+ (incomplete, inherent_associated_types, "1.52.0", Some(8995), None),
+ /// Allow anonymous constants from an inline `const` block
+ (active, inline_const, "1.49.0", Some(76001), None),
+ /// Allow anonymous constants from an inline `const` block in pattern position
+ (incomplete, inline_const_pat, "1.58.0", Some(76001), None),
+ /// Allows using `pointer` and `reference` in intra-doc links
+ (active, intra_doc_pointers, "1.51.0", Some(80896), None),
+ /// Allows `#[instruction_set(_)]` attribute
+ (active, isa_attribute, "1.48.0", Some(74727), None),
+ /// Allows `'a: { break 'a; }`.
+ (active, label_break_value, "1.28.0", Some(48594), None),
+ // Allows setting the threshold for the `large_assignments` lint.
+ (active, large_assignments, "1.52.0", Some(83518), None),
+ /// Allows `if/while p && let q = r && ...` chains.
+ (active, let_chains, "1.37.0", Some(53667), None),
+ /// Allows `let...else` statements.
+ (active, let_else, "1.56.0", Some(87335), None),
+ /// Allows `#[link(..., cfg(..))]`.
+ (active, link_cfg, "1.14.0", Some(37406), None),
+ /// Allows using `reason` in lint attributes and the `#[expect(lint)]` lint check.
+ (active, lint_reasons, "1.31.0", Some(54503), None),
+ /// Give access to additional metadata about declarative macro meta-variables.
+ (active, macro_metavar_expr, "1.61.0", Some(83527), None),
+ /// Allows `#[marker]` on certain traits allowing overlapping implementations.
+ (active, marker_trait_attr, "1.30.0", Some(29864), None),
+ /// A minimal, sound subset of specialization intended to be used by the
+ /// standard library until the soundness issues with specialization
+ /// are fixed.
+ (active, min_specialization, "1.7.0", Some(31844), None),
+ /// Allows qualified paths in struct expressions, struct patterns and tuple struct patterns.
+ (active, more_qualified_paths, "1.54.0", Some(86935), None),
+ /// Allows the `#[must_not_suspend]` attribute.
+ (active, must_not_suspend, "1.57.0", Some(83310), None),
+ /// Allows using `#[naked]` on functions.
+ (active, naked_functions, "1.9.0", Some(32408), None),
+ /// Allows specifying the as-needed link modifier
+ (active, native_link_modifiers_as_needed, "1.53.0", Some(81490), None),
+ /// Allows specifying the verbatim link modifier
+ (active, native_link_modifiers_verbatim, "1.53.0", Some(81490), None),
+ /// Allow negative trait implementations.
+ (active, negative_impls, "1.44.0", Some(68318), None),
+ /// Allows the `!` type. Does not imply 'exhaustive_patterns' (below) any more.
+ (active, never_type, "1.13.0", Some(35121), None),
+ /// Allows diverging expressions to fall back to `!` rather than `()`.
+ (active, never_type_fallback, "1.41.0", Some(65992), None),
+ /// Allows `#![no_core]`.
+ (active, no_core, "1.3.0", Some(29639), None),
+ /// Allows function attribute `#[no_coverage]`, to bypass coverage
+ /// instrumentation of that function.
+ (active, no_coverage, "1.53.0", Some(84605), None),
+ /// Allows the use of `no_sanitize` attribute.
+ (active, no_sanitize, "1.42.0", Some(39699), None),
+ /// Allows using the `non_exhaustive_omitted_patterns` lint.
+ (active, non_exhaustive_omitted_patterns_lint, "1.57.0", Some(89554), None),
+ /// Allows making `dyn Trait` well-formed even if `Trait` is not object safe.
+ /// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and
+ /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden.
+ (active, object_safe_for_dispatch, "1.40.0", Some(43561), None),
+ /// Allows using `#[optimize(X)]`.
+ (active, optimize_attribute, "1.34.0", Some(54882), None),
+ /// Allows `extern "platform-intrinsic" { ... }`.
+ (active, platform_intrinsics, "1.4.0", Some(27731), None),
+ /// Allows using `#![plugin(myplugin)]`.
+ (active, plugin, "1.0.0", Some(29597), None),
+ /// Allows exhaustive integer pattern matching on `usize` and `isize`.
+ (active, precise_pointer_size_matching, "1.32.0", Some(56354), None),
+ /// Allows macro attributes on expressions, statements and non-inline modules.
+ (active, proc_macro_hygiene, "1.30.0", Some(54727), None),
+ /// Allows the use of raw-dylibs (RFC 2627).
+ (incomplete, raw_dylib, "1.40.0", Some(58713), None),
+ /// Allows `&raw const $place_expr` and `&raw mut $place_expr` expressions.
+ (active, raw_ref_op, "1.41.0", Some(64490), None),
+ /// Allows using the `#[register_attr]` attribute.
+ (active, register_attr, "1.41.0", Some(66080), None),
+ /// Allows using the `#[register_tool]` attribute.
+ (active, register_tool, "1.41.0", Some(66079), None),
+ /// Allows the `#[repr(i128)]` attribute for enums.
+ (incomplete, repr128, "1.16.0", Some(56071), None),
+ /// Allows `repr(simd)` and importing the various simd intrinsics.
+ (active, repr_simd, "1.4.0", Some(27731), None),
+ /// Allows `extern "rust-cold"`.
+ (active, rust_cold_cc, "1.63.0", Some(97544), None),
+ /// Allows the use of SIMD types in functions declared in `extern` blocks.
+ (active, simd_ffi, "1.0.0", Some(27731), None),
+ /// Allows specialization of implementations (RFC 1210).
+ (incomplete, specialization, "1.7.0", Some(31844), None),
+ /// Allows attributes on expressions and non-item statements.
+ (active, stmt_expr_attributes, "1.6.0", Some(15701), None),
+ /// Allows lints part of the strict provenance effort.
+ (active, strict_provenance, "1.61.0", Some(95228), None),
+ /// Allows the use of `#[target_feature]` on safe functions.
+ (active, target_feature_11, "1.45.0", Some(69098), None),
+ /// Allows using `#[thread_local]` on `static` items.
+ (active, thread_local, "1.0.0", Some(29594), None),
+ /// Allows defining `trait X = A + B;` alias items.
+ (active, trait_alias, "1.24.0", Some(41517), None),
+ /// Allows upcasting trait objects via supertraits.
+ /// Trait upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`.
+ (incomplete, trait_upcasting, "1.56.0", Some(65991), None),
+ /// Allows #[repr(transparent)] on unions (RFC 2645).
+ (active, transparent_unions, "1.37.0", Some(60405), None),
+ /// Allows inconsistent bounds in where clauses.
+ (active, trivial_bounds, "1.28.0", Some(48214), None),
+ /// Allows using `try {...}` expressions.
+ (active, try_blocks, "1.29.0", Some(31436), None),
+ /// Allows `impl Trait` to be used inside type aliases (RFC 2515).
+ (active, type_alias_impl_trait, "1.38.0", Some(63063), None),
+ /// Allows the use of type ascription in expressions.
+ (active, type_ascription, "1.6.0", Some(23416), None),
+ /// Allows creation of instances of a struct by moving fields that have
+ /// not changed from prior instances of the same struct (RFC #2528)
+ (active, type_changing_struct_update, "1.58.0", Some(86555), None),
+ /// Allows unsized fn parameters.
+ (active, unsized_fn_params, "1.49.0", Some(48055), None),
+ /// Allows unsized rvalues at arguments and parameters.
+ (incomplete, unsized_locals, "1.30.0", Some(48055), None),
+ /// Allows unsized tuple coercion.
+ (active, unsized_tuple_coercion, "1.20.0", Some(42877), None),
+ /// Allows using the `#[used(linker)]` (or `#[used(compiler)]`) attribute.
+ (active, used_with_arg, "1.60.0", Some(93798), None),
+ /// Allows `extern "wasm" fn`
+ (active, wasm_abi, "1.53.0", Some(83788), None),
+ /// Allows `do yeet` expressions
+ (active, yeet_expr, "1.62.0", Some(96373), None),
+ // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!
+ // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way.
+ // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!
+
+ // -------------------------------------------------------------------------
+ // feature-group-end: actual feature gates
+ // -------------------------------------------------------------------------
+);
+
+/// Some features are not allowed to be used together at the same time, if
+/// the two are present, produce an error.
+///
+/// Currently empty, but we will probably need this again in the future,
+/// so let's keep it in for now.
+pub const INCOMPATIBLE_FEATURES: &[(Symbol, Symbol)] = &[];
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
new file mode 100644
index 000000000..0e73d8fd7
--- /dev/null
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -0,0 +1,833 @@
+//! Built-in attributes and `cfg` flag gating.
+
+use AttributeDuplicates::*;
+use AttributeGate::*;
+use AttributeType::*;
+
+use crate::{Features, Stability};
+
+use rustc_data_structures::fx::FxHashMap;
+use rustc_span::symbol::{sym, Symbol};
+
+use std::sync::LazyLock;
+
+type GateFn = fn(&Features) -> bool;
+
+macro_rules! cfg_fn {
+ ($field: ident) => {
+ (|features| features.$field) as GateFn
+ };
+}
+
+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::target_abi, sym::cfg_target_abi, cfg_fn!(cfg_target_abi)),
+ (sym::target_thread_local, sym::cfg_target_thread_local, cfg_fn!(cfg_target_thread_local)),
+ (
+ sym::target_has_atomic_equal_alignment,
+ sym::cfg_target_has_atomic_equal_alignment,
+ cfg_fn!(cfg_target_has_atomic_equal_alignment),
+ ),
+ (sym::target_has_atomic_load_store, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)),
+ (sym::sanitize, sym::cfg_sanitize, cfg_fn!(cfg_sanitize)),
+ (sym::version, sym::cfg_version, cfg_fn!(cfg_version)),
+];
+
+/// 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))
+}
+
+// If you change this, please modify `src/doc/unstable-book` as well. You must
+// move that documentation into the relevant place in the other docs, and
+// remove the chapter on the flag.
+
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub enum AttributeType {
+ /// Normal, builtin attribute that is consumed
+ /// by the compiler before the unused_attribute check
+ Normal,
+
+ /// Builtin attribute that is only allowed at the crate level
+ CrateLevel,
+}
+
+#[derive(Clone, Copy)]
+pub enum AttributeGate {
+ /// Is gated by a given feature gate, reason
+ /// and function to check if enabled
+ Gated(Stability, Symbol, &'static str, fn(&Features) -> bool),
+
+ /// Ungated attribute, can be used on all release channels
+ Ungated,
+}
+
+// fn() is not Debug
+impl std::fmt::Debug for AttributeGate {
+ fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match *self {
+ Self::Gated(ref stab, name, expl, _) => {
+ write!(fmt, "Gated({:?}, {}, {})", stab, name, expl)
+ }
+ Self::Ungated => write!(fmt, "Ungated"),
+ }
+ }
+}
+
+impl AttributeGate {
+ fn is_deprecated(&self) -> bool {
+ matches!(*self, Self::Gated(Stability::Deprecated(_, _), ..))
+ }
+}
+
+/// A template that the attribute input must match.
+/// Only top-level shape (`#[attr]` vs `#[attr(...)]` vs `#[attr = ...]`) is considered now.
+#[derive(Clone, Copy, Default)]
+pub struct AttributeTemplate {
+ /// If `true`, the attribute is allowed to be a bare word like `#[test]`.
+ pub word: bool,
+ /// If `Some`, the attribute is allowed to take a list of items like `#[allow(..)]`.
+ pub list: Option<&'static str>,
+ /// If `Some`, the attribute is allowed to be a name/value pair where the
+ /// value is a string, like `#[must_use = "reason"]`.
+ pub name_value_str: Option<&'static str>,
+}
+
+/// How to handle multiple duplicate attributes on the same item.
+#[derive(Clone, Copy, Default)]
+pub enum AttributeDuplicates {
+ /// Duplicates of this attribute are allowed.
+ ///
+ /// This should only be used with attributes where duplicates have semantic
+ /// meaning, or some kind of "additive" behavior. For example, `#[warn(..)]`
+ /// can be specified multiple times, and it combines all the entries. Or use
+ /// this if there is validation done elsewhere.
+ #[default]
+ DuplicatesOk,
+ /// Duplicates after the first attribute will be an unused_attribute warning.
+ ///
+ /// This is usually used for "word" attributes, where they are used as a
+ /// boolean marker, like `#[used]`. It is not necessarily wrong that there
+ /// are duplicates, but the others should probably be removed.
+ WarnFollowing,
+ /// Same as `WarnFollowing`, but only issues warnings for word-style attributes.
+ ///
+ /// This is only for special cases, for example multiple `#[macro_use]` can
+ /// be warned, but multiple `#[macro_use(...)]` should not because the list
+ /// form has different meaning from the word form.
+ WarnFollowingWordOnly,
+ /// Duplicates after the first attribute will be an error.
+ ///
+ /// This should be used where duplicates would be ignored, but carry extra
+ /// meaning that could cause confusion. For example, `#[stable(since="1.0")]
+ /// #[stable(since="2.0")]`, which version should be used for `stable`?
+ ErrorFollowing,
+ /// Duplicates preceding the last instance of the attribute will be an error.
+ ///
+ /// This is the same as `ErrorFollowing`, except the last attribute is the
+ /// one that is "used". This is typically used in cases like codegen
+ /// attributes which usually only honor the last attribute.
+ ErrorPreceding,
+ /// Duplicates after the first attribute will be an unused_attribute warning
+ /// with a note that this will be an error in the future.
+ ///
+ /// This should be used for attributes that should be `ErrorFollowing`, but
+ /// because older versions of rustc silently accepted (and ignored) the
+ /// attributes, this is used to transition.
+ FutureWarnFollowing,
+ /// Duplicates preceding the last instance of the attribute will be a
+ /// warning, with a note that this will be an error in the future.
+ ///
+ /// This is the same as `FutureWarnFollowing`, except the last attribute is
+ /// the one that is "used". Ideally these can eventually migrate to
+ /// `ErrorPreceding`.
+ FutureWarnPreceding,
+}
+
+/// A conveniece macro to deal with `$($expr)?`.
+macro_rules! or_default {
+ ($default:expr,) => {
+ $default
+ };
+ ($default:expr, $next:expr) => {
+ $next
+ };
+}
+
+/// A convenience macro for constructing attribute templates.
+/// E.g., `template!(Word, List: "description")` means that the attribute
+/// supports forms `#[attr]` and `#[attr(description)]`.
+macro_rules! template {
+ (Word) => { template!(@ true, None, None) };
+ (List: $descr: expr) => { template!(@ false, Some($descr), None) };
+ (NameValueStr: $descr: expr) => { template!(@ false, None, Some($descr)) };
+ (Word, List: $descr: expr) => { template!(@ true, Some($descr), None) };
+ (Word, NameValueStr: $descr: expr) => { template!(@ true, None, Some($descr)) };
+ (List: $descr1: expr, NameValueStr: $descr2: expr) => {
+ template!(@ false, Some($descr1), Some($descr2))
+ };
+ (Word, List: $descr1: expr, NameValueStr: $descr2: expr) => {
+ template!(@ true, Some($descr1), Some($descr2))
+ };
+ (@ $word: expr, $list: expr, $name_value_str: expr) => { AttributeTemplate {
+ word: $word, list: $list, name_value_str: $name_value_str
+ } };
+}
+
+macro_rules! ungated {
+ ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr $(, @only_local: $only_local:expr)? $(,)?) => {
+ BuiltinAttribute {
+ name: sym::$attr,
+ only_local: or_default!(false, $($only_local)?),
+ type_: $typ,
+ template: $tpl,
+ gate: Ungated,
+ duplicates: $duplicates,
+ }
+ };
+}
+
+macro_rules! gated {
+ ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr $(, @only_local: $only_local:expr)?, $gate:ident, $msg:expr $(,)?) => {
+ BuiltinAttribute {
+ name: sym::$attr,
+ only_local: or_default!(false, $($only_local)?),
+ type_: $typ,
+ template: $tpl,
+ duplicates: $duplicates,
+ gate: Gated(Stability::Unstable, sym::$gate, $msg, cfg_fn!($gate)),
+ }
+ };
+ ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr $(, @only_local: $only_local:expr)?, $msg:expr $(,)?) => {
+ BuiltinAttribute {
+ name: sym::$attr,
+ only_local: or_default!(false, $($only_local)?),
+ type_: $typ,
+ template: $tpl,
+ duplicates: $duplicates,
+ gate: Gated(Stability::Unstable, sym::$attr, $msg, cfg_fn!($attr)),
+ }
+ };
+}
+
+macro_rules! rustc_attr {
+ (TEST, $attr:ident, $typ:expr, $tpl:expr, $duplicate:expr $(, @only_local: $only_local:expr)? $(,)?) => {
+ rustc_attr!(
+ $attr,
+ $typ,
+ $tpl,
+ $duplicate,
+ $(@only_local: $only_local,)?
+ concat!(
+ "the `#[",
+ stringify!($attr),
+ "]` attribute is just used for rustc unit tests \
+ and will never be stable",
+ ),
+ )
+ };
+ ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr $(, @only_local: $only_local:expr)?, $msg:expr $(,)?) => {
+ BuiltinAttribute {
+ name: sym::$attr,
+ only_local: or_default!(false, $($only_local)?),
+ type_: $typ,
+ template: $tpl,
+ duplicates: $duplicates,
+ gate: Gated(Stability::Unstable, sym::rustc_attrs, $msg, cfg_fn!(rustc_attrs)),
+ }
+ };
+}
+
+macro_rules! experimental {
+ ($attr:ident) => {
+ concat!("the `#[", stringify!($attr), "]` attribute is an experimental feature")
+ };
+}
+
+const IMPL_DETAIL: &str = "internal implementation detail";
+const INTERNAL_UNSTABLE: &str = "this is an internal attribute that will never be stable";
+
+pub struct BuiltinAttribute {
+ pub name: Symbol,
+ /// Whether this attribute is only used in the local crate.
+ ///
+ /// If so, it is not encoded in the crate metadata.
+ pub only_local: bool,
+ pub type_: AttributeType,
+ pub template: AttributeTemplate,
+ pub duplicates: AttributeDuplicates,
+ pub gate: AttributeGate,
+}
+
+/// Attributes that have a special meaning to rustc or rustdoc.
+#[rustfmt::skip]
+pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
+ // ==========================================================================
+ // Stable attributes:
+ // ==========================================================================
+
+ // Conditional compilation:
+ ungated!(cfg, Normal, template!(List: "predicate"), DuplicatesOk),
+ ungated!(cfg_attr, Normal, template!(List: "predicate, attr1, attr2, ..."), DuplicatesOk),
+
+ // Testing:
+ ungated!(ignore, Normal, template!(Word, NameValueStr: "reason"), WarnFollowing),
+ ungated!(
+ should_panic, Normal,
+ template!(Word, List: r#"expected = "reason"#, NameValueStr: "reason"), FutureWarnFollowing,
+ ),
+ // FIXME(Centril): This can be used on stable but shouldn't.
+ ungated!(reexport_test_harness_main, CrateLevel, template!(NameValueStr: "name"), ErrorFollowing),
+
+ // Macros:
+ ungated!(automatically_derived, Normal, template!(Word), WarnFollowing),
+ ungated!(macro_use, Normal, template!(Word, List: "name1, name2, ..."), WarnFollowingWordOnly),
+ ungated!(macro_escape, Normal, template!(Word), WarnFollowing), // Deprecated synonym for `macro_use`.
+ ungated!(macro_export, Normal, template!(Word, List: "local_inner_macros"), WarnFollowing),
+ ungated!(proc_macro, Normal, template!(Word), ErrorFollowing),
+ ungated!(
+ proc_macro_derive, Normal,
+ template!(List: "TraitName, /*opt*/ attributes(name1, name2, ...)"), ErrorFollowing,
+ ),
+ ungated!(proc_macro_attribute, Normal, template!(Word), ErrorFollowing),
+
+ // Lints:
+ ungated!(
+ warn, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk
+ ),
+ ungated!(
+ allow, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk
+ ),
+ gated!(
+ expect, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk,
+ lint_reasons, experimental!(expect)
+ ),
+ ungated!(
+ forbid, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk
+ ),
+ ungated!(
+ deny, Normal, template!(List: r#"lint1, lint2, ..., /*opt*/ reason = "...""#), DuplicatesOk
+ ),
+ ungated!(must_use, Normal, template!(Word, NameValueStr: "reason"), FutureWarnFollowing),
+ gated!(
+ must_not_suspend, Normal, template!(Word, NameValueStr: "reason"), WarnFollowing,
+ experimental!(must_not_suspend)
+ ),
+ ungated!(
+ deprecated, Normal,
+ template!(
+ Word,
+ List: r#"/*opt*/ since = "version", /*opt*/ note = "reason""#,
+ NameValueStr: "reason"
+ ),
+ ErrorFollowing
+ ),
+
+ // Crate properties:
+ ungated!(crate_name, CrateLevel, template!(NameValueStr: "name"), FutureWarnFollowing),
+ ungated!(crate_type, CrateLevel, template!(NameValueStr: "bin|lib|..."), DuplicatesOk),
+ // crate_id is deprecated
+ ungated!(crate_id, CrateLevel, template!(NameValueStr: "ignored"), FutureWarnFollowing),
+
+ // ABI, linking, symbols, and FFI
+ ungated!(
+ link, Normal,
+ template!(List: r#"name = "...", /*opt*/ kind = "dylib|static|...", /*opt*/ wasm_import_module = "...""#),
+ DuplicatesOk,
+ ),
+ ungated!(link_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding),
+ ungated!(no_link, Normal, template!(Word), WarnFollowing),
+ ungated!(repr, Normal, template!(List: "C"), DuplicatesOk),
+ ungated!(export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding),
+ ungated!(link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding),
+ ungated!(no_mangle, Normal, template!(Word), WarnFollowing, @only_local: true),
+ ungated!(used, Normal, template!(Word, List: "compiler|linker"), WarnFollowing, @only_local: true),
+
+ // Limits:
+ ungated!(recursion_limit, CrateLevel, template!(NameValueStr: "N"), FutureWarnFollowing),
+ ungated!(type_length_limit, CrateLevel, template!(NameValueStr: "N"), FutureWarnFollowing),
+ gated!(
+ const_eval_limit, CrateLevel, template!(NameValueStr: "N"), ErrorFollowing,
+ const_eval_limit, experimental!(const_eval_limit)
+ ),
+ gated!(
+ move_size_limit, CrateLevel, template!(NameValueStr: "N"), ErrorFollowing,
+ large_assignments, experimental!(move_size_limit)
+ ),
+
+ // Entry point:
+ ungated!(start, Normal, template!(Word), WarnFollowing),
+ ungated!(no_start, CrateLevel, template!(Word), WarnFollowing),
+ ungated!(no_main, CrateLevel, template!(Word), WarnFollowing),
+
+ // Modules, prelude, and resolution:
+ ungated!(path, Normal, template!(NameValueStr: "file"), FutureWarnFollowing),
+ ungated!(no_std, CrateLevel, template!(Word), WarnFollowing),
+ ungated!(no_implicit_prelude, Normal, template!(Word), WarnFollowing),
+ ungated!(non_exhaustive, Normal, template!(Word), WarnFollowing),
+
+ // Runtime
+ ungated!(
+ windows_subsystem, CrateLevel,
+ template!(NameValueStr: "windows|console"), FutureWarnFollowing
+ ),
+ ungated!(panic_handler, Normal, template!(Word), WarnFollowing), // RFC 2070
+
+ // Code generation:
+ ungated!(inline, Normal, template!(Word, List: "always|never"), FutureWarnFollowing, @only_local: true),
+ ungated!(cold, Normal, template!(Word), WarnFollowing, @only_local: true),
+ ungated!(no_builtins, CrateLevel, template!(Word), WarnFollowing),
+ ungated!(target_feature, Normal, template!(List: r#"enable = "name""#), DuplicatesOk),
+ ungated!(track_caller, Normal, template!(Word), WarnFollowing),
+ gated!(
+ no_sanitize, Normal,
+ template!(List: "address, memory, thread"), DuplicatesOk,
+ experimental!(no_sanitize)
+ ),
+ gated!(no_coverage, Normal, template!(Word), WarnFollowing, experimental!(no_coverage)),
+
+ ungated!(
+ doc, Normal, template!(List: "hidden|inline|...", NameValueStr: "string"), DuplicatesOk
+ ),
+
+ // ==========================================================================
+ // Unstable attributes:
+ // ==========================================================================
+
+ // RFC #3191: #[debugger_visualizer] support
+ gated!(
+ debugger_visualizer, Normal, template!(List: r#"natvis_file = "...", gdb_script_file = "...""#),
+ DuplicatesOk, experimental!(debugger_visualizer)
+ ),
+
+ // Linking:
+ gated!(naked, Normal, template!(Word), WarnFollowing, @only_local: true, naked_functions, experimental!(naked)),
+ gated!(
+ link_ordinal, Normal, template!(List: "ordinal"), ErrorPreceding, raw_dylib,
+ experimental!(link_ordinal)
+ ),
+
+ // Plugins:
+ BuiltinAttribute {
+ name: sym::plugin,
+ only_local: false,
+ type_: CrateLevel,
+ template: template!(List: "name"),
+ duplicates: DuplicatesOk,
+ gate: Gated(
+ Stability::Deprecated(
+ "https://github.com/rust-lang/rust/pull/64675",
+ Some("may be removed in a future compiler version"),
+ ),
+ sym::plugin,
+ "compiler plugins are deprecated",
+ cfg_fn!(plugin)
+ ),
+ },
+
+ // Testing:
+ gated!(
+ test_runner, CrateLevel, template!(List: "path"), ErrorFollowing, custom_test_frameworks,
+ "custom test frameworks are an unstable feature",
+ ),
+ // RFC #1268
+ gated!(
+ marker, Normal, template!(Word), WarnFollowing, marker_trait_attr, experimental!(marker)
+ ),
+ gated!(
+ thread_local, Normal, template!(Word), WarnFollowing,
+ "`#[thread_local]` is an experimental feature, and does not currently handle destructors",
+ ),
+ gated!(no_core, CrateLevel, template!(Word), WarnFollowing, experimental!(no_core)),
+ // RFC 2412
+ gated!(
+ optimize, Normal, template!(List: "size|speed"), ErrorPreceding, optimize_attribute,
+ experimental!(optimize),
+ ),
+ // RFC 2867
+ gated!(
+ instruction_set, Normal, template!(List: "set"), ErrorPreceding,
+ isa_attribute, experimental!(instruction_set)
+ ),
+
+ gated!(
+ ffi_returns_twice, Normal, template!(Word), WarnFollowing, experimental!(ffi_returns_twice)
+ ),
+ gated!(ffi_pure, Normal, template!(Word), WarnFollowing, experimental!(ffi_pure)),
+ gated!(ffi_const, Normal, template!(Word), WarnFollowing, experimental!(ffi_const)),
+ gated!(
+ register_attr, CrateLevel, template!(List: "attr1, attr2, ..."), DuplicatesOk,
+ experimental!(register_attr),
+ ),
+ gated!(
+ register_tool, CrateLevel, template!(List: "tool1, tool2, ..."), DuplicatesOk,
+ experimental!(register_tool),
+ ),
+
+ gated!(
+ cmse_nonsecure_entry, Normal, template!(Word), WarnFollowing,
+ experimental!(cmse_nonsecure_entry)
+ ),
+ // RFC 2632
+ gated!(
+ const_trait, Normal, template!(Word), WarnFollowing, const_trait_impl,
+ "`const` is a temporary placeholder for marking a trait that is suitable for `const` \
+ `impls` and all default bodies as `const`, which may be removed or renamed in the \
+ future."
+ ),
+ // lang-team MCP 147
+ gated!(
+ deprecated_safe, Normal, template!(List: r#"since = "version", note = "...""#), ErrorFollowing,
+ experimental!(deprecated_safe),
+ ),
+
+ // ==========================================================================
+ // Internal attributes: Stability, deprecation, and unsafe:
+ // ==========================================================================
+
+ ungated!(feature, CrateLevel, template!(List: "name1, name2, ..."), DuplicatesOk),
+ // DuplicatesOk since it has its own validation
+ ungated!(
+ stable, Normal, template!(List: r#"feature = "name", since = "version""#), DuplicatesOk,
+ ),
+ ungated!(
+ unstable, Normal,
+ template!(List: r#"feature = "name", reason = "...", issue = "N""#), DuplicatesOk,
+ ),
+ ungated!(rustc_const_unstable, Normal, template!(List: r#"feature = "name""#), DuplicatesOk),
+ ungated!(rustc_const_stable, Normal, template!(List: r#"feature = "name""#), DuplicatesOk),
+ gated!(
+ allow_internal_unstable, Normal, template!(Word, List: "feat1, feat2, ..."), DuplicatesOk,
+ "allow_internal_unstable side-steps feature gating and stability checks",
+ ),
+ gated!(
+ rustc_allow_const_fn_unstable, Normal,
+ template!(Word, List: "feat1, feat2, ..."), DuplicatesOk,
+ "rustc_allow_const_fn_unstable side-steps feature gating and stability checks"
+ ),
+ gated!(
+ allow_internal_unsafe, Normal, template!(Word), WarnFollowing,
+ "allow_internal_unsafe side-steps the unsafe_code lint",
+ ),
+ rustc_attr!(rustc_allowed_through_unstable_modules, Normal, template!(Word), WarnFollowing,
+ "rustc_allowed_through_unstable_modules special cases accidental stabilizations of stable items \
+ through unstable paths"),
+
+ // ==========================================================================
+ // Internal attributes: Type system related:
+ // ==========================================================================
+
+ gated!(fundamental, Normal, template!(Word), WarnFollowing, experimental!(fundamental)),
+ gated!(
+ may_dangle, Normal, template!(Word), WarnFollowing, dropck_eyepatch,
+ "`may_dangle` has unstable semantics and may be removed in the future",
+ ),
+
+ // ==========================================================================
+ // Internal attributes: Runtime related:
+ // ==========================================================================
+
+ rustc_attr!(rustc_allocator, Normal, template!(Word), WarnFollowing, IMPL_DETAIL),
+ rustc_attr!(rustc_allocator_nounwind, Normal, template!(Word), WarnFollowing, IMPL_DETAIL),
+ rustc_attr!(rustc_reallocator, Normal, template!(Word), WarnFollowing, IMPL_DETAIL),
+ rustc_attr!(rustc_deallocator, Normal, template!(Word), WarnFollowing, IMPL_DETAIL),
+ rustc_attr!(rustc_allocator_zeroed, Normal, template!(Word), WarnFollowing, IMPL_DETAIL),
+ gated!(
+ alloc_error_handler, Normal, template!(Word), WarnFollowing,
+ experimental!(alloc_error_handler)
+ ),
+ gated!(
+ default_lib_allocator, Normal, template!(Word), WarnFollowing, allocator_internals,
+ experimental!(default_lib_allocator),
+ ),
+ gated!(
+ needs_allocator, Normal, template!(Word), WarnFollowing, allocator_internals,
+ experimental!(needs_allocator),
+ ),
+ gated!(panic_runtime, Normal, template!(Word), WarnFollowing, experimental!(panic_runtime)),
+ gated!(
+ needs_panic_runtime, Normal, template!(Word), WarnFollowing,
+ experimental!(needs_panic_runtime)
+ ),
+ gated!(
+ compiler_builtins, Normal, template!(Word), WarnFollowing,
+ "the `#[compiler_builtins]` attribute is used to identify the `compiler_builtins` crate \
+ which contains compiler-rt intrinsics and will never be stable",
+ ),
+ gated!(
+ profiler_runtime, Normal, template!(Word), WarnFollowing,
+ "the `#[profiler_runtime]` attribute is used to identify the `profiler_builtins` crate \
+ which contains the profiler runtime and will never be stable",
+ ),
+
+ // ==========================================================================
+ // Internal attributes, Linkage:
+ // ==========================================================================
+
+ gated!(
+ linkage, Normal, template!(NameValueStr: "external|internal|..."), ErrorPreceding, @only_local: true,
+ "the `linkage` attribute is experimental and not portable across platforms",
+ ),
+ rustc_attr!(
+ rustc_std_internal_symbol, Normal, template!(Word), WarnFollowing, @only_local: true, INTERNAL_UNSTABLE
+ ),
+
+ // ==========================================================================
+ // Internal attributes, Macro related:
+ // ==========================================================================
+
+ rustc_attr!(
+ rustc_builtin_macro, Normal,
+ template!(Word, List: "name, /*opt*/ attributes(name1, name2, ...)"), ErrorFollowing,
+ IMPL_DETAIL,
+ ),
+ rustc_attr!(rustc_proc_macro_decls, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE),
+ rustc_attr!(
+ rustc_macro_transparency, Normal,
+ template!(NameValueStr: "transparent|semitransparent|opaque"), ErrorFollowing,
+ "used internally for testing macro hygiene",
+ ),
+
+ // ==========================================================================
+ // Internal attributes, Diagnostics related:
+ // ==========================================================================
+
+ rustc_attr!(
+ rustc_on_unimplemented, Normal,
+ template!(
+ List: r#"/*opt*/ message = "...", /*opt*/ label = "...", /*opt*/ note = "...""#,
+ NameValueStr: "message"
+ ),
+ ErrorFollowing,
+ INTERNAL_UNSTABLE
+ ),
+ // Enumerates "identity-like" conversion methods to suggest on type mismatch.
+ rustc_attr!(
+ rustc_conversion_suggestion, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE
+ ),
+ // Prevents field reads in the marked trait or method to be considered
+ // during dead code analysis.
+ rustc_attr!(
+ rustc_trivial_field_reads, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE
+ ),
+ // Used by the `rustc::potential_query_instability` lint to warn methods which
+ // might not be stable during incremental compilation.
+ rustc_attr!(rustc_lint_query_instability, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE),
+ // Used by the `rustc::untranslatable_diagnostic` and `rustc::diagnostic_outside_of_impl` lints
+ // to assist in changes to diagnostic APIs.
+ rustc_attr!(rustc_lint_diagnostics, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE),
+ // Used by the `rustc::bad_opt_access` lint to identify `DebuggingOptions` and `CodegenOptions`
+ // types (as well as any others in future).
+ rustc_attr!(rustc_lint_opt_ty, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE),
+ // Used by the `rustc::bad_opt_access` lint on fields
+ // types (as well as any others in future).
+ rustc_attr!(rustc_lint_opt_deny_field_access, Normal, template!(List: "message"), WarnFollowing, INTERNAL_UNSTABLE),
+
+ // ==========================================================================
+ // Internal attributes, Const related:
+ // ==========================================================================
+
+ rustc_attr!(rustc_promotable, Normal, template!(Word), WarnFollowing, IMPL_DETAIL),
+ rustc_attr!(
+ rustc_legacy_const_generics, Normal, template!(List: "N"), ErrorFollowing,
+ INTERNAL_UNSTABLE
+ ),
+ // Do not const-check this function's body. It will always get replaced during CTFE.
+ rustc_attr!(
+ rustc_do_not_const_check, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE
+ ),
+
+ // ==========================================================================
+ // Internal attributes, Layout related:
+ // ==========================================================================
+
+ rustc_attr!(
+ rustc_layout_scalar_valid_range_start, Normal, template!(List: "value"), ErrorFollowing,
+ "the `#[rustc_layout_scalar_valid_range_start]` attribute is just used to enable \
+ niche optimizations in libcore and libstd and will never be stable",
+ ),
+ rustc_attr!(
+ rustc_layout_scalar_valid_range_end, Normal, template!(List: "value"), ErrorFollowing,
+ "the `#[rustc_layout_scalar_valid_range_end]` attribute is just used to enable \
+ niche optimizations in libcore and libstd and will never be stable",
+ ),
+ rustc_attr!(
+ rustc_nonnull_optimization_guaranteed, Normal, template!(Word), WarnFollowing,
+ "the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to enable \
+ niche optimizations in libcore and libstd and will never be stable",
+ ),
+
+ // ==========================================================================
+ // Internal attributes, Misc:
+ // ==========================================================================
+ gated!(
+ lang, Normal, template!(NameValueStr: "name"), DuplicatesOk, @only_local: true, lang_items,
+ "language items are subject to change",
+ ),
+ rustc_attr!(
+ rustc_pass_by_value, Normal,
+ template!(Word), ErrorFollowing,
+ "#[rustc_pass_by_value] is used to mark types that must be passed by value instead of reference."
+ ),
+ rustc_attr!(
+ rustc_coherence_is_core, AttributeType::CrateLevel, template!(Word), ErrorFollowing, @only_local: true,
+ "#![rustc_coherence_is_core] allows inherent methods on builtin types, only intended to be used in `core`."
+ ),
+ rustc_attr!(
+ rustc_allow_incoherent_impl, AttributeType::Normal, template!(Word), ErrorFollowing, @only_local: true,
+ "#[rustc_allow_incoherent_impl] has to be added to all impl items of an incoherent inherent impl."
+ ),
+ rustc_attr!(
+ rustc_has_incoherent_inherent_impls, AttributeType::Normal, template!(Word), ErrorFollowing,
+ "#[rustc_has_incoherent_inherent_impls] allows the addition of incoherent inherent impls for \
+ the given type by annotating all impl items with #[rustc_allow_incoherent_impl]."
+ ),
+ rustc_attr!(
+ rustc_box, AttributeType::Normal, template!(Word), ErrorFollowing,
+ "#[rustc_box] allows creating boxes \
+ and it is only intended to be used in `alloc`."
+ ),
+
+ BuiltinAttribute {
+ name: sym::rustc_diagnostic_item,
+ // FIXME: This can be `true` once we always use `tcx.is_diagnostic_item`.
+ only_local: false,
+ type_: Normal,
+ template: template!(NameValueStr: "name"),
+ duplicates: ErrorFollowing,
+ gate: Gated(
+ Stability::Unstable,
+ sym::rustc_attrs,
+ "diagnostic items compiler internal support for linting",
+ cfg_fn!(rustc_attrs),
+ ),
+ },
+ gated!(
+ // Used in resolve:
+ prelude_import, Normal, template!(Word), WarnFollowing,
+ "`#[prelude_import]` is for use by rustc only",
+ ),
+ gated!(
+ rustc_paren_sugar, Normal, template!(Word), WarnFollowing, unboxed_closures,
+ "unboxed_closures are still evolving",
+ ),
+ rustc_attr!(
+ rustc_inherit_overflow_checks, Normal, template!(Word), WarnFollowing, @only_local: true,
+ "the `#[rustc_inherit_overflow_checks]` attribute is just used to control \
+ overflow checking behavior of several libcore functions that are inlined \
+ across crates and will never be stable",
+ ),
+ rustc_attr!(
+ rustc_reservation_impl, Normal,
+ template!(NameValueStr: "reservation message"), ErrorFollowing,
+ "the `#[rustc_reservation_impl]` attribute is internally used \
+ for reserving for `for<T> From<!> for T` impl"
+ ),
+ rustc_attr!(
+ rustc_test_marker, Normal, template!(Word), WarnFollowing,
+ "the `#[rustc_test_marker]` attribute is used internally to track tests",
+ ),
+ rustc_attr!(
+ rustc_unsafe_specialization_marker, Normal, template!(Word), WarnFollowing,
+ "the `#[rustc_unsafe_specialization_marker]` attribute is used to check specializations"
+ ),
+ rustc_attr!(
+ rustc_specialization_trait, Normal, template!(Word), WarnFollowing,
+ "the `#[rustc_specialization_trait]` attribute is used to check specializations"
+ ),
+ rustc_attr!(
+ rustc_main, Normal, template!(Word), WarnFollowing,
+ "the `#[rustc_main]` attribute is used internally to specify test entry point function",
+ ),
+ rustc_attr!(
+ rustc_skip_array_during_method_dispatch, Normal, template!(Word), WarnFollowing,
+ "the `#[rustc_skip_array_during_method_dispatch]` attribute is used to exclude a trait \
+ from method dispatch when the receiver is an array, for compatibility in editions < 2021."
+ ),
+ rustc_attr!(
+ rustc_must_implement_one_of, Normal, template!(List: "function1, function2, ..."), ErrorFollowing,
+ "the `#[rustc_must_implement_one_of]` attribute is used to change minimal complete \
+ definition of a trait, it's currently in experimental form and should be changed before \
+ being exposed outside of the std"
+ ),
+
+ // ==========================================================================
+ // Internal attributes, Testing:
+ // ==========================================================================
+
+ rustc_attr!(TEST, rustc_outlives, Normal, template!(Word), WarnFollowing),
+ rustc_attr!(TEST, rustc_capture_analysis, Normal, template!(Word), WarnFollowing),
+ rustc_attr!(TEST, rustc_insignificant_dtor, Normal, template!(Word), WarnFollowing),
+ rustc_attr!(TEST, rustc_strict_coherence, Normal, template!(Word), WarnFollowing),
+ rustc_attr!(TEST, rustc_variance, Normal, template!(Word), WarnFollowing),
+ rustc_attr!(TEST, rustc_layout, Normal, template!(List: "field1, field2, ..."), WarnFollowing),
+ rustc_attr!(TEST, rustc_regions, Normal, template!(Word), WarnFollowing),
+ rustc_attr!(
+ TEST, rustc_error, Normal,
+ template!(Word, List: "delay_span_bug_from_inside_query"), WarnFollowingWordOnly
+ ),
+ rustc_attr!(TEST, rustc_dump_user_substs, Normal, template!(Word), WarnFollowing),
+ rustc_attr!(TEST, rustc_evaluate_where_clauses, Normal, template!(Word), WarnFollowing),
+ rustc_attr!(
+ TEST, rustc_if_this_changed, Normal, template!(Word, List: "DepNode"), DuplicatesOk
+ ),
+ rustc_attr!(
+ TEST, rustc_then_this_would_need, Normal, template!(List: "DepNode"), DuplicatesOk
+ ),
+ rustc_attr!(
+ TEST, rustc_clean, Normal,
+ template!(List: r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#),
+ DuplicatesOk,
+ ),
+ rustc_attr!(
+ TEST, rustc_partition_reused, Normal,
+ template!(List: r#"cfg = "...", module = "...""#), DuplicatesOk,
+ ),
+ rustc_attr!(
+ TEST, rustc_partition_codegened, Normal,
+ template!(List: r#"cfg = "...", module = "...""#), DuplicatesOk,
+ ),
+ rustc_attr!(
+ TEST, rustc_expected_cgu_reuse, Normal,
+ template!(List: r#"cfg = "...", module = "...", kind = "...""#), DuplicatesOk,
+ ),
+ rustc_attr!(TEST, rustc_symbol_name, Normal, template!(Word), WarnFollowing),
+ rustc_attr!(TEST, rustc_polymorphize_error, Normal, template!(Word), WarnFollowing),
+ rustc_attr!(TEST, rustc_def_path, Normal, template!(Word), WarnFollowing),
+ rustc_attr!(TEST, rustc_mir, Normal, template!(List: "arg1, arg2, ..."), DuplicatesOk),
+ rustc_attr!(TEST, rustc_dump_program_clauses, Normal, template!(Word), WarnFollowing),
+ rustc_attr!(TEST, rustc_dump_env_program_clauses, Normal, template!(Word), WarnFollowing),
+ rustc_attr!(TEST, rustc_object_lifetime_default, Normal, template!(Word), WarnFollowing),
+ rustc_attr!(TEST, rustc_dump_vtable, Normal, template!(Word), WarnFollowing),
+ rustc_attr!(TEST, rustc_dummy, Normal, template!(Word /* doesn't matter*/), DuplicatesOk),
+ gated!(
+ omit_gdb_pretty_printer_section, Normal, template!(Word), WarnFollowing,
+ "the `#[omit_gdb_pretty_printer_section]` attribute is just used for the Rust test suite",
+ ),
+];
+
+pub fn deprecated_attributes() -> Vec<&'static BuiltinAttribute> {
+ BUILTIN_ATTRIBUTES.iter().filter(|attr| attr.gate.is_deprecated()).collect()
+}
+
+pub fn is_builtin_attr_name(name: Symbol) -> bool {
+ BUILTIN_ATTRIBUTE_MAP.get(&name).is_some()
+}
+
+pub fn is_builtin_only_local(name: Symbol) -> bool {
+ BUILTIN_ATTRIBUTE_MAP.get(&name).map_or(false, |attr| attr.only_local)
+}
+
+pub static BUILTIN_ATTRIBUTE_MAP: LazyLock<FxHashMap<Symbol, &BuiltinAttribute>> =
+ LazyLock::new(|| {
+ let mut map = FxHashMap::default();
+ for attr in BUILTIN_ATTRIBUTES.iter() {
+ if map.insert(attr.name, attr).is_some() {
+ panic!("duplicate builtin attribute `{}`", attr.name);
+ }
+ }
+ map
+ });
diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs
new file mode 100644
index 000000000..efb830527
--- /dev/null
+++ b/compiler/rustc_feature/src/lib.rs
@@ -0,0 +1,155 @@
+//! # Feature gates
+//!
+//! This crate declares the set of past and present unstable features in the compiler.
+//! Feature gate checking itself is done in `rustc_ast_passes/src/feature_gate.rs`
+//! at the moment.
+//!
+//! Features are enabled in programs via the crate-level attributes of
+//! `#![feature(...)]` with a comma-separated list of features.
+//!
+//! For the purpose of future feature-tracking, once a feature gate is added,
+//! even if it is stabilized or removed, *do not remove it*. Instead, move the
+//! symbol to the `accepted` or `removed` modules respectively.
+
+#![feature(once_cell)]
+
+mod accepted;
+mod active;
+mod builtin_attrs;
+mod removed;
+
+#[cfg(test)]
+mod tests;
+
+use rustc_span::{edition::Edition, symbol::Symbol, Span};
+use std::fmt;
+use std::num::NonZeroU32;
+
+#[derive(Clone, Copy)]
+pub enum State {
+ Accepted,
+ Active { set: fn(&mut Features, Span) },
+ Removed { reason: Option<&'static str> },
+ Stabilized { reason: Option<&'static str> },
+}
+
+impl fmt::Debug for State {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ State::Accepted { .. } => write!(f, "accepted"),
+ State::Active { .. } => write!(f, "active"),
+ State::Removed { .. } => write!(f, "removed"),
+ State::Stabilized { .. } => write!(f, "stabilized"),
+ }
+ }
+}
+
+#[derive(Debug, Clone)]
+pub struct Feature {
+ pub state: State,
+ pub name: Symbol,
+ pub since: &'static str,
+ issue: Option<NonZeroU32>,
+ pub edition: Option<Edition>,
+}
+
+#[derive(Copy, Clone, Debug)]
+pub enum Stability {
+ Unstable,
+ // First argument is tracking issue link; second argument is an optional
+ // help message, which defaults to "remove this attribute".
+ Deprecated(&'static str, Option<&'static str>),
+}
+
+#[derive(Clone, Copy, Debug, Hash)]
+pub enum UnstableFeatures {
+ /// Hard errors for unstable features are active, as on beta/stable channels.
+ Disallow,
+ /// Allow features to be activated, as on nightly.
+ Allow,
+ /// Errors are bypassed for bootstrapping. This is required any time
+ /// during the build that feature-related lints are set to warn or above
+ /// because the build turns on warnings-as-errors and uses lots of unstable
+ /// features. As a result, this is always required for building Rust itself.
+ Cheat,
+}
+
+impl UnstableFeatures {
+ /// This takes into account `RUSTC_BOOTSTRAP`.
+ ///
+ /// If `krate` is [`Some`], then setting `RUSTC_BOOTSTRAP=krate` will enable the nightly features.
+ /// Otherwise, only `RUSTC_BOOTSTRAP=1` will work.
+ pub fn from_environment(krate: Option<&str>) -> Self {
+ // `true` if this is a feature-staged build, i.e., on the beta or stable channel.
+ let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
+ // Returns whether `krate` should be counted as unstable
+ let is_unstable_crate = |var: &str| {
+ krate.map_or(false, |name| var.split(',').any(|new_krate| new_krate == name))
+ };
+ // `true` if we should enable unstable features for bootstrapping.
+ let bootstrap = std::env::var("RUSTC_BOOTSTRAP")
+ .map_or(false, |var| var == "1" || is_unstable_crate(&var));
+ match (disable_unstable_features, bootstrap) {
+ (_, true) => UnstableFeatures::Cheat,
+ (true, _) => UnstableFeatures::Disallow,
+ (false, _) => UnstableFeatures::Allow,
+ }
+ }
+
+ pub fn is_nightly_build(&self) -> bool {
+ match *self {
+ UnstableFeatures::Allow | UnstableFeatures::Cheat => true,
+ UnstableFeatures::Disallow => false,
+ }
+ }
+}
+
+fn find_lang_feature_issue(feature: Symbol) -> Option<NonZeroU32> {
+ if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.name == feature) {
+ // FIXME (#28244): enforce that active features have issue numbers
+ // assert!(info.issue.is_some())
+ info.issue
+ } else {
+ // search in Accepted, Removed, or Stable Removed features
+ let found = ACCEPTED_FEATURES
+ .iter()
+ .chain(REMOVED_FEATURES)
+ .chain(STABLE_REMOVED_FEATURES)
+ .find(|t| t.name == feature);
+ match found {
+ Some(found) => found.issue,
+ None => panic!("feature `{}` is not declared anywhere", feature),
+ }
+ }
+}
+
+const fn to_nonzero(n: Option<u32>) -> Option<NonZeroU32> {
+ // Can be replaced with `n.and_then(NonZeroU32::new)` if that is ever usable
+ // in const context. Requires https://github.com/rust-lang/rfcs/pull/2632.
+ match n {
+ None => None,
+ Some(n) => NonZeroU32::new(n),
+ }
+}
+
+pub enum GateIssue {
+ Language,
+ Library(Option<NonZeroU32>),
+}
+
+pub fn find_feature_issue(feature: Symbol, issue: GateIssue) -> Option<NonZeroU32> {
+ match issue {
+ GateIssue::Language => find_lang_feature_issue(feature),
+ GateIssue::Library(lib) => lib,
+ }
+}
+
+pub use accepted::ACCEPTED_FEATURES;
+pub use active::{Features, ACTIVE_FEATURES, INCOMPATIBLE_FEATURES};
+pub use builtin_attrs::AttributeDuplicates;
+pub use builtin_attrs::{
+ deprecated_attributes, find_gated_cfg, is_builtin_attr_name, is_builtin_only_local,
+ AttributeGate, AttributeTemplate, AttributeType, BuiltinAttribute, GatedCfg,
+ BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP,
+};
+pub use removed::{REMOVED_FEATURES, STABLE_REMOVED_FEATURES};
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
new file mode 100644
index 000000000..2ddaf9201
--- /dev/null
+++ b/compiler/rustc_feature/src/removed.rs
@@ -0,0 +1,203 @@
+//! List of the removed feature gates.
+
+use super::{to_nonzero, Feature, State};
+use rustc_span::symbol::sym;
+
+macro_rules! declare_features {
+ ($(
+ $(#[doc = $doc:tt])* (removed, $feature:ident, $ver:expr, $issue:expr, None, $reason:expr),
+ )+) => {
+ /// Represents unstable features which have since been removed (it was once Active)
+ pub const REMOVED_FEATURES: &[Feature] = &[
+ $(
+ Feature {
+ state: State::Removed { reason: $reason },
+ name: sym::$feature,
+ since: $ver,
+ issue: to_nonzero($issue),
+ edition: None,
+ }
+ ),+
+ ];
+ };
+
+ ($(
+ $(#[doc = $doc:tt])* (stable_removed, $feature:ident, $ver:expr, $issue:expr, None),
+ )+) => {
+ /// Represents stable features which have since been removed (it was once Accepted)
+ pub const STABLE_REMOVED_FEATURES: &[Feature] = &[
+ $(
+ Feature {
+ state: State::Stabilized { reason: None },
+ name: sym::$feature,
+ since: $ver,
+ issue: to_nonzero($issue),
+ edition: None,
+ }
+ ),+
+ ];
+ };
+}
+
+#[rustfmt::skip]
+declare_features! (
+ // -------------------------------------------------------------------------
+ // feature-group-start: removed features
+ // -------------------------------------------------------------------------
+
+ (removed, advanced_slice_patterns, "1.0.0", Some(62254), None,
+ Some("merged into `#![feature(slice_patterns)]`")),
+ (removed, allocator, "1.0.0", None, None, None),
+ /// Allows a test to fail without failing the whole suite.
+ (removed, allow_fail, "1.19.0", Some(46488), None, Some("removed due to no clear use cases")),
+ (removed, await_macro, "1.38.0", Some(50547), None,
+ Some("subsumed by `.await` syntax")),
+ /// Allows comparing raw pointers during const eval.
+ (removed, const_compare_raw_pointers, "1.46.0", Some(53020), None,
+ Some("cannot be allowed in const eval in any meaningful way")),
+ /// Allows non-trivial generic constants which have to be manually propagated upwards.
+ (removed, const_evaluatable_checked, "1.48.0", Some(76560), None, Some("renamed to `generic_const_exprs`")),
+ /// Allows the definition of `const` functions with some advanced features.
+ (removed, const_fn, "1.54.0", Some(57563), None,
+ Some("split into finer-grained feature gates")),
+ /// Allows const generic types (e.g. `struct Foo<const N: usize>(...);`).
+ (removed, const_generics, "1.34.0", Some(44580), None,
+ Some("removed in favor of `#![feature(adt_const_params)]` and `#![feature(generic_const_exprs)]`")),
+ /// Allows `[x; N]` where `x` is a constant (RFC 2203).
+ (removed, const_in_array_repeat_expressions, "1.37.0", Some(49147), None,
+ Some("removed due to causing promotable bugs")),
+ /// Allows casting raw pointers to `usize` during const eval.
+ (removed, const_raw_ptr_to_usize_cast, "1.55.0", Some(51910), None,
+ Some("at compile-time, pointers do not have an integer value, so these casts cannot be properly supported")),
+ /// Allows `T: ?const Trait` syntax in bounds.
+ (removed, const_trait_bound_opt_out, "1.42.0", Some(67794), None,
+ Some("Removed in favor of `~const` bound in #![feature(const_trait_impl)]")),
+ /// Allows using `crate` as visibility modifier, synonymous with `pub(crate)`.
+ (removed, crate_visibility_modifier, "1.63.0", Some(53120), None, Some("removed in favor of `pub(crate)`")),
+ /// Allows using custom attributes (RFC 572).
+ (removed, custom_attribute, "1.0.0", Some(29642), None,
+ Some("removed in favor of `#![register_tool]` and `#![register_attr]`")),
+ /// Allows the use of `#[derive(Anything)]` as sugar for `#[derive_Anything]`.
+ (removed, custom_derive, "1.32.0", Some(29644), None,
+ Some("subsumed by `#[proc_macro_derive]`")),
+ /// Allows using `#[doc(keyword = "...")]`.
+ (removed, doc_keyword, "1.28.0", Some(51315), None,
+ Some("merged into `#![feature(rustdoc_internals)]`")),
+ /// Allows using `doc(primitive)` without a future-incompat warning.
+ (removed, doc_primitive, "1.56.0", Some(88070), None,
+ Some("merged into `#![feature(rustdoc_internals)]`")),
+ /// Allows `#[doc(spotlight)]`.
+ /// The attribute was renamed to `#[doc(notable_trait)]`
+ /// and the feature to `doc_notable_trait`.
+ (removed, doc_spotlight, "1.22.0", Some(45040), None,
+ Some("renamed to `doc_notable_trait`")),
+ /// Allows using `#[unsafe_destructor_blind_to_params]` (RFC 1238).
+ (removed, dropck_parametricity, "1.38.0", Some(28498), None, None),
+ /// Allows defining `existential type`s.
+ (removed, existential_type, "1.38.0", Some(63063), None,
+ Some("removed in favor of `#![feature(type_alias_impl_trait)]`")),
+ /// Paths of the form: `extern::foo::bar`
+ (removed, extern_in_paths, "1.33.0", Some(55600), None,
+ Some("subsumed by `::foo::bar` paths")),
+ /// Allows `#[doc(include = "some-file")]`.
+ (removed, external_doc, "1.54.0", Some(44732), None,
+ Some("use #[doc = include_str!(\"filename\")] instead, which handles macro invocations")),
+ /// Allows `impl Trait` in bindings (`let`, `const`, `static`).
+ (removed, impl_trait_in_bindings, "1.55.0", Some(63065), None,
+ Some("the implementation was not maintainable, the feature may get reintroduced once the current refactorings are done")),
+ (removed, import_shadowing, "1.0.0", None, None, None),
+ /// Allows in-band quantification of lifetime bindings (e.g., `fn foo(x: &'a u8) -> &'a u8`).
+ (removed, in_band_lifetimes, "1.23.0", Some(44524), None,
+ Some("removed due to unsolved ergonomic questions and added lifetime resolution complexity")),
+ /// Allows inferring `'static` outlives requirements (RFC 2093).
+ (removed, infer_static_outlives_requirements, "1.63.0", Some(54185), None,
+ Some("removed as it caused some confusion and discussion was inactive for years")),
+ /// Lazily evaluate constants. This allows constants to depend on type parameters.
+ (removed, lazy_normalization_consts, "1.46.0", Some(72219), None, Some("superseded by `generic_const_exprs`")),
+ /// Allows using the `#[link_args]` attribute.
+ (removed, link_args, "1.53.0", Some(29596), None,
+ Some("removed in favor of using `-C link-arg=ARG` on command line, \
+ which is available from cargo build scripts with `cargo:rustc-link-arg` now")),
+ (removed, macro_reexport, "1.0.0", Some(29638), None,
+ Some("subsumed by `pub use`")),
+ /// Allows using `#[main]` to replace the entrypoint `#[lang = "start"]` calls.
+ (removed, main, "1.53.0", Some(29634), None, None),
+ (removed, managed_boxes, "1.0.0", None, None, None),
+ /// Allows the use of type alias impl trait in function return positions
+ (removed, min_type_alias_impl_trait, "1.56.0", Some(63063), None,
+ Some("removed in favor of full type_alias_impl_trait")),
+ (removed, needs_allocator, "1.4.0", Some(27389), None,
+ Some("subsumed by `#![feature(allocator_internals)]`")),
+ /// Allows use of unary negate on unsigned integers, e.g., -e for e: u8
+ (removed, negate_unsigned, "1.0.0", Some(29645), None, None),
+ /// Allows `#[no_debug]`.
+ (removed, no_debug, "1.43.0", Some(29721), None, Some("removed due to lack of demand")),
+ /// Allows using `#[on_unimplemented(..)]` on traits.
+ /// (Moved to `rustc_attrs`.)
+ (removed, on_unimplemented, "1.40.0", None, None, None),
+ /// A way to temporarily opt out of opt in copy. This will *never* be accepted.
+ (removed, opt_out_copy, "1.0.0", None, None, None),
+ /// Allows features specific to OIBIT (now called auto traits).
+ /// Renamed to `auto_traits`.
+ (removed, optin_builtin_traits, "1.0.0", Some(13231), None,
+ Some("renamed to `auto_traits`")),
+ /// Allows overlapping impls of marker traits.
+ (removed, overlapping_marker_traits, "1.42.0", Some(29864), None,
+ Some("removed in favor of `#![feature(marker_trait_attr)]`")),
+ (removed, panic_implementation, "1.28.0", Some(44489), None,
+ Some("subsumed by `#[panic_handler]`")),
+ /// Allows using `#[plugin_registrar]` on functions.
+ (removed, plugin_registrar, "1.54.0", Some(29597), None,
+ Some("a __rustc_plugin_registrar symbol must now be defined instead")),
+ (removed, proc_macro_expr, "1.27.0", Some(54727), None,
+ Some("subsumed by `#![feature(proc_macro_hygiene)]`")),
+ (removed, proc_macro_gen, "1.27.0", Some(54727), None,
+ Some("subsumed by `#![feature(proc_macro_hygiene)]`")),
+ (removed, proc_macro_mod, "1.27.0", Some(54727), None,
+ Some("subsumed by `#![feature(proc_macro_hygiene)]`")),
+ (removed, proc_macro_non_items, "1.27.0", Some(54727), None,
+ Some("subsumed by `#![feature(proc_macro_hygiene)]`")),
+ (removed, pub_macro_rules, "1.53.0", Some(78855), None,
+ Some("removed due to being incomplete, in particular it does not work across crates")),
+ (removed, pushpop_unsafe, "1.2.0", None, None, None),
+ (removed, quad_precision_float, "1.0.0", None, None, None),
+ (removed, quote, "1.33.0", Some(29601), None, None),
+ (removed, reflect, "1.0.0", Some(27749), None, None),
+ /// Allows using the macros:
+ /// + `__diagnostic_used`
+ /// + `__register_diagnostic`
+ /// +`__build_diagnostic_array`
+ (removed, rustc_diagnostic_macros, "1.38.0", None, None, None),
+ /// Allows identifying crates that contain sanitizer runtimes.
+ (removed, sanitizer_runtime, "1.17.0", None, None, None),
+ (removed, simd, "1.0.0", Some(27731), None,
+ Some("removed in favor of `#[repr(simd)]`")),
+ /// Allows `#[link(kind = "static-nobundle", ...)]`.
+ (removed, static_nobundle, "1.16.0", Some(37403), None,
+ Some(r#"subsumed by `#[link(kind = "static", modifiers = "-bundle", ...)]`"#)),
+ (removed, struct_inherit, "1.0.0", None, None, None),
+ (removed, test_removed_feature, "1.0.0", None, None, None),
+ /// Allows using items which are missing stability attributes
+ (removed, unmarked_api, "1.0.0", None, None, None),
+ (removed, unsafe_no_drop_flag, "1.0.0", None, None, None),
+ /// Allows `union` fields that don't implement `Copy` as long as they don't have any drop glue.
+ (removed, untagged_unions, "1.13.0", Some(55149), None,
+ Some("unions with `Copy` and `ManuallyDrop` fields are stable; there is no intent to stabilize more")),
+ /// Allows `#[unwind(..)]`.
+ ///
+ /// Permits specifying whether a function should permit unwinding or abort on unwind.
+ (removed, unwind_attributes, "1.56.0", Some(58760), None, Some("use the C-unwind ABI instead")),
+ (removed, visible_private_types, "1.0.0", None, None, None),
+ // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!
+ // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way.
+ // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!
+
+ // -------------------------------------------------------------------------
+ // feature-group-end: removed features
+ // -------------------------------------------------------------------------
+);
+
+#[rustfmt::skip]
+declare_features! (
+ (stable_removed, no_stack_check, "1.0.0", None, None),
+);
diff --git a/compiler/rustc_feature/src/tests.rs b/compiler/rustc_feature/src/tests.rs
new file mode 100644
index 000000000..50433e44b
--- /dev/null
+++ b/compiler/rustc_feature/src/tests.rs
@@ -0,0 +1,23 @@
+use super::UnstableFeatures;
+
+#[test]
+fn rustc_bootstrap_parsing() {
+ let is_bootstrap = |env, krate| {
+ std::env::set_var("RUSTC_BOOTSTRAP", env);
+ matches!(UnstableFeatures::from_environment(krate), UnstableFeatures::Cheat)
+ };
+ assert!(is_bootstrap("1", None));
+ assert!(is_bootstrap("1", Some("x")));
+ // RUSTC_BOOTSTRAP allows specifying a specific crate
+ assert!(is_bootstrap("x", Some("x")));
+ // RUSTC_BOOTSTRAP allows multiple comma-delimited crates
+ assert!(is_bootstrap("x,y,z", Some("x")));
+ assert!(is_bootstrap("x,y,z", Some("y")));
+ // Crate that aren't specified do not get unstable features
+ assert!(!is_bootstrap("x", Some("a")));
+ assert!(!is_bootstrap("x,y,z", Some("a")));
+ assert!(!is_bootstrap("x,y,z", None));
+
+ // this is technically a breaking change, but there are no stability guarantees for RUSTC_BOOTSTRAP
+ assert!(!is_bootstrap("0", None));
+}