Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 22 additions & 2 deletions compiler/rustc_expand/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
use rustc_errors::msg;
use rustc_feature::{
ACCEPTED_LANG_FEATURES, EnabledLangFeature, EnabledLibFeature, Features, REMOVED_LANG_FEATURES,
UNSTABLE_LANG_FEATURES,
RENAMED_LANG_FEATURES, UNSTABLE_LANG_FEATURES,
};
use rustc_hir::attrs::AttributeKind;
use rustc_hir::{
Expand All @@ -33,7 +33,7 @@ use tracing::instrument;

use crate::errors::{
CrateNameInCfgAttr, CrateTypeInCfgAttr, FeatureNotAllowed, FeatureRemoved,
FeatureRemovedReason, InvalidCfg, RemoveExprNotSupported,
FeatureRemovedReason, FeatureRenamed, InvalidCfg, RemoveExprNotSupported,
};

/// A folder that strips out items that do not belong in the current configuration.
Expand Down Expand Up @@ -81,6 +81,26 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) -
continue;
}

// The old name is deprecated in favor of a new one, point the user at it
if let Some(f) =
RENAMED_LANG_FEATURES.iter().find(|f| feature_ident.name == f.feature.name)
{
let pull_note = if let Some(pull) = f.pull {
format!(
"; see <https://github.com/rust-lang/rust/pull/{pull}> for more information",
)
} else {
"".to_owned()
};
sess.dcx().emit_err(FeatureRenamed {
span: feature_ident.span,
new_name: f.new_name,
renamed_rustc_version: f.feature.since,
pull_note,
});
continue;
}

// If the enabled feature is stable, record it.
if let Some(f) = ACCEPTED_LANG_FEATURES.iter().find(|f| feature_ident.name == f.name) {
features.set_enabled_lang_feature(EnabledLangFeature {
Expand Down
17 changes: 17 additions & 0 deletions compiler/rustc_expand/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,23 @@ pub(crate) struct FeatureRemoved<'a> {
pub pull_note: String,
}

#[derive(Diagnostic)]
#[diag("feature was renamed", code = E0557)]
#[note("renamed in {$renamed_rustc_version}{$pull_note}")]
pub(crate) struct FeatureRenamed<'a> {
#[primary_span]
#[suggestion(
"update to the new name",
code = "{new_name}",
applicability = "machine-applicable"
)]
#[label("feature was renamed")]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this label duplicates a message from diag

Copy link
Copy Markdown
Contributor Author

@nik-rev nik-rev Apr 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

old diagnostic had the same label and diagnostic message, so I just mirrored that:

- error[E0557]: feature has been removed
+ error[E0557]: feature was renamed
    --> $DIR/feature-gate-sanitize.rs:1:12
     |
  LL | #![feature(no_sanitize)]
-    |            ^^^^^^^^^^^ feature has been removed
+    |            ^^^^^^^^^^^
+    |            |
+    |            feature was renamed
+    |            help: update to the new name: `sanitize`

Copy link
Copy Markdown
Member

@Kivooeo Kivooeo Apr 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, let's drop it from both in a follow up, or remvoe it from renamed now and from removed in a follow up, smth like this

pub span: Span,
pub new_name: &'a str,
pub renamed_rustc_version: &'a str,
pub pull_note: String,
}

#[derive(Subdiagnostic)]
#[note("{$reason}")]
pub(crate) struct FeatureRemovedReason<'a> {
Expand Down
17 changes: 17 additions & 0 deletions compiler/rustc_feature/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,13 @@
//! 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.
//!
//! If a feature is renamed, move it to the `renamed` module.

mod accepted;
mod builtin_attrs;
mod removed;
mod renamed;
mod unstable;

#[cfg(test)]
Expand Down Expand Up @@ -103,6 +106,9 @@ fn find_lang_feature_issue(feature: Symbol) -> Option<NonZero<u32>> {
if let Some(f) = REMOVED_LANG_FEATURES.iter().find(|f| f.feature.name == feature) {
return f.feature.issue;
}
if let Some(f) = RENAMED_LANG_FEATURES.iter().find(|f| f.feature.name == feature) {
return f.feature.issue;
}
panic!("feature `{feature}` is not declared anywhere");
}

Expand Down Expand Up @@ -135,7 +141,18 @@ pub use builtin_attrs::{
is_valid_for_get_attr,
};
pub use removed::REMOVED_LANG_FEATURES;
pub use renamed::{RENAMED_LANG_FEATURES, RenamedFeature};
pub use unstable::{
DEPENDENT_FEATURES, EnabledLangFeature, EnabledLibFeature, Features, INCOMPATIBLE_FEATURES,
TRACK_FEATURE, UNSTABLE_LANG_FEATURES,
};

macro_rules! opt_nonzero_u32 {
() => {
None
};
($val:expr) => {
Some(core::num::NonZeroU32::new($val).unwrap())
};
}
pub(crate) use opt_nonzero_u32;
38 changes: 2 additions & 36 deletions compiler/rustc_feature/src/removed.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,18 @@
//! List of the removed feature gates.

use std::num::{NonZero, NonZeroU32};
use std::num::NonZero;

use rustc_span::sym;

use super::{Feature, to_nonzero};
use crate::opt_nonzero_u32;

pub struct RemovedFeature {
pub feature: Feature,
pub reason: Option<&'static str>,
pub pull: Option<NonZero<u32>>,
}

macro_rules! opt_nonzero_u32 {
() => {
None
};
($val:expr) => {
Some(NonZeroU32::new($val).unwrap())
};
}

macro_rules! declare_features {
($(
$(#[doc = $doc:tt])* (removed, $feature:ident, $ver:expr, $issue:expr, $reason:expr $(, $pull:expr)?),
Expand Down Expand Up @@ -54,7 +46,6 @@ declare_features! (

/// Allows using the `amdgpu-kernel` ABI.
(removed, abi_amdgpu_kernel, "1.77.0", Some(51575), None, 120495),
(removed, abi_c_cmse_nonsecure_call, "1.90.0", Some(81391), Some("renamed to abi_cmse_nonsecure_call"), 142146),
(removed, advanced_slice_patterns, "1.42.0", Some(62254),
Some("merged into `#![feature(slice_patterns)]`"), 67712),
(removed, allocator, "1.0.0", None, None),
Expand All @@ -74,8 +65,6 @@ declare_features! (
Some("cannot be allowed in const eval in any meaningful way"), 73398),
/// Allows limiting the evaluation steps of const expressions
(removed, const_eval_limit, "1.72.0", Some(67217), Some("removed the limit entirely"), 103877),
/// Allows non-trivial generic constants which have to be manually propagated upwards.
(removed, const_evaluatable_checked, "1.56.0", Some(76560), Some("renamed to `generic_const_exprs`"), 88369),
/// Allows the definition of `const` functions with some advanced features.
(removed, const_fn, "1.54.0", Some(57563),
Some("split into finer-grained feature gates"), 85109),
Expand Down Expand Up @@ -116,11 +105,6 @@ declare_features! (
/// Allows using `doc(primitive)` without a future-incompat warning.
(removed, doc_primitive, "1.58.0", Some(88070),
Some("merged into `#![feature(rustdoc_internals)]`"), 90420),
/// Allows `#[doc(spotlight)]`.
/// The attribute was renamed to `#[doc(notable_trait)]`
/// and the feature to `doc_notable_trait`.
(removed, doc_spotlight, "1.53.0", Some(45040),
Some("renamed to `doc_notable_trait`"), 80965),
/// Allows using `#[unsafe_destructor_blind_to_params]` (RFC 1238).
(removed, dropck_parametricity, "1.38.0", Some(28498), None),
/// Allows making `dyn Trait` well-formed even if `Trait` is not dyn compatible[^1].
Expand Down Expand Up @@ -150,10 +134,6 @@ declare_features! (
/// Allows using `#[ffi_returns_twice]` on foreign functions.
(removed, ffi_returns_twice, "1.78.0", Some(58314),
Some("being investigated by the ffi-unwind project group"), 120502),
/// Allows generators to be cloned.
(removed, generator_clone, "1.75.0", Some(95360), Some("renamed to `coroutine_clone`"), 116958),
/// Allows defining generators.
(removed, generators, "1.75.0", Some(43122), Some("renamed to `coroutines`"), 116958),
/// An extension to the `generic_associated_types` feature, allowing incomplete features.
(removed, generic_associated_types_extended, "1.85.0", Some(95451),
Some(
Expand Down Expand Up @@ -199,34 +179,20 @@ declare_features! (
(removed, negate_unsigned, "1.0.0", Some(29645), None),
/// Allows diverging expressions to fall back to `!` rather than `()`.
(removed, never_type_fallback, "1.93.0", Some(65992), Some("removed in favor of unconditional fallback"), 148871),
/// Allows `#[no_coverage]` on functions.
/// The feature was renamed to `coverage_attribute` and the attribute to `#[coverage(on|off)]`
(removed, no_coverage, "1.74.0", Some(84605), Some("renamed to `coverage_attribute`"), 114656),
/// Allows `#[no_debug]`.
(removed, no_debug, "1.43.0", Some(29721), Some("removed due to lack of demand"), 69667),
// Allows the use of `no_sanitize` attribute.
/// The feature was renamed to `sanitize` and the attribute to `#[sanitize(xyz = "on|off")]`
(removed, no_sanitize, "1.91.0", Some(39699), Some(r#"renamed to sanitize(xyz = "on|off")"#), 142681),
/// Note: this feature was previously recorded in a separate
/// `STABLE_REMOVED` list because it, uniquely, was once stable but was
/// then removed. But there was no utility storing it separately, so now
/// it's in this list.
(removed, no_stack_check, "1.0.0", None, None, 40110),
/// Allows making `dyn Trait` well-formed even if `Trait` is not dyn compatible (object safe).
/// Renamed to `dyn_compatible_for_dispatch`.
(removed, object_safe_for_dispatch, "1.83.0", Some(43561),
Some("renamed to `dyn_compatible_for_dispatch`"), 131511),
/// Allows using `#[omit_gdb_pretty_printer_section]`.
(removed, omit_gdb_pretty_printer_section, "1.91.0", None, None, 144738),
/// Allows using `#[on_unimplemented(..)]` on traits.
/// (Moved to `rustc_attrs`.)
(removed, on_unimplemented, "1.40.0", None, None, 65794),
/// A way to temporarily opt out of opt-in copy. This will *never* be accepted.
(removed, opt_out_copy, "1.0.0", None, None, 20740),
/// Allows features specific to OIBIT (now called auto traits).
/// Renamed to `auto_traits`.
(removed, optin_builtin_traits, "1.50.0", Some(13231),
Some("renamed to `auto_traits`"), 79336),
/// Allows overlapping impls of marker traits.
(removed, overlapping_marker_traits, "1.42.0", Some(29864),
Some("removed in favor of `#![feature(marker_trait_attr)]`"), 68544),
Expand Down
86 changes: 86 additions & 0 deletions compiler/rustc_feature/src/renamed.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
//! List of the renamed feature gates.

use std::num::NonZero;

use rustc_span::sym;

use super::{Feature, to_nonzero};
use crate::opt_nonzero_u32;

pub struct RenamedFeature {
pub feature: Feature,
pub new_name: &'static str,
pub pull: Option<NonZero<u32>>,
}

macro_rules! declare_features {
($(
$(#[doc = $doc:tt])* (renamed, $old_feature_name:ident => $new_feature_name:ident, $ver:expr, $issue:expr $(, $pull:expr)?),
)+) => {
/// Features that have been renamed.
pub static RENAMED_LANG_FEATURES: &[RenamedFeature] = &[
$(RenamedFeature {
feature: Feature {
name: sym::$old_feature_name,
since: $ver,
issue: to_nonzero($issue),
},
new_name: stringify!($new_feature_name),
pull: opt_nonzero_u32!($($pull)?),
}),+
];
};
}

#[rustfmt::skip]
declare_features! {
// -------------------------------------------------------------------------
// feature-group-start: renamed features
// -------------------------------------------------------------------------

// Note that the version indicates when it got *renamed*.
//
// When renaming a feature, set the version number to
// `CURRENT RUSTC VERSION` with ` ` replaced by `_`.

(renamed, abi_c_cmse_nonsecure_call => abi_cmse_nonsecure_call, "1.90.0", Some(81391), 142146),
/// Allows non-trivial generic constants which have to be manually propagated upwards.
(renamed, const_evaluatable_checked => generic_const_exprs, "1.56.0", Some(76560), 88369),
/// Allows `#[doc(spotlight)]`.
/// The attribute was renamed to `#[doc(notable_trait)]`
/// and the feature to `doc_notable_trait`.
(renamed, doc_spotlight => doc_notable_trait, "1.53.0", Some(45040), 80965),
/// Allows generators to be cloned.
(renamed, generator_clone => coroutine_clone, "1.75.0", Some(95360), 116958),
/// Allows defining generators.
(renamed, generators => coroutines, "1.75.0", Some(43122), 116958),
/// Allows `#[no_coverage]` on functions.
/// The feature was renamed to `coverage_attribute` and the attribute to `#[coverage(on|off)]`
(renamed, no_coverage => coverage_attribute, "1.74.0", Some(84605), 114656),
// Allows the use of `no_sanitize` attribute.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should it be a doc comment?

/// The feature was renamed to `sanitize` and the attribute to `#[sanitize(xyz = "on|off")]`
(renamed, no_sanitize => sanitize, "1.91.0", Some(39699), 142681),
/// Allows making `dyn Trait` well-formed even if `Trait` is not dyn compatible (object safe).
/// Renamed to `dyn_compatible_for_dispatch`.
(renamed, object_safe_for_dispatch => dyn_compatible_for_dispatch, "1.83.0", Some(43561), 131511),
/// Allows features specific to OIBIT (now called auto traits).
/// Renamed to `auto_traits`.
(renamed, optin_builtin_traits => auto_traits, "1.50.0", Some(13231), 79336),

// -------------------------------------------------------------------------
// feature-group-end: renamed features
// -------------------------------------------------------------------------


// -------------------------------------------------------------------------
// feature-group-start: renamed library features
// -------------------------------------------------------------------------
//
// FIXME(#141617): we should have a better way to track renamed library features, but we reuse
// the infrastructure here so users still get hints. The symbols used here can be remove from
// `symbol.rs` when that happens.

// -------------------------------------------------------------------------
// feature-group-end: renamed library features
// -------------------------------------------------------------------------
}
Loading
Loading