Tracking the old name of renamed unstable library attribute

Signed-off-by: xizheyin <xizheyin@smail.nju.edu.cn>
This commit is contained in:
xizheyin
2025-06-07 18:57:33 +08:00
parent 8eeaed06ea
commit b8066f94fd
20 changed files with 58 additions and 33 deletions

View File

@@ -132,6 +132,7 @@ pub enum StabilityLevel {
/// fn foobar() {}
/// ```
implied_by: Option<Symbol>,
old_name: Option<Symbol>,
},
/// `#[stable]`
Stable {

View File

@@ -299,6 +299,7 @@ pub(crate) fn parse_unstability(
let mut issue_num = None;
let mut is_soft = false;
let mut implied_by = None;
let mut old_name = None;
for param in args.list()?.mixed() {
let Some(param) = param.meta_item() else {
cx.emit_err(session_diagnostics::UnsupportedLiteral {
@@ -346,11 +347,12 @@ pub(crate) fn parse_unstability(
Some(sym::implied_by) => {
insert_value_into_option_or_error(cx, &param, &mut implied_by)?
}
Some(sym::old_name) => insert_value_into_option_or_error(cx, &param, &mut old_name)?,
_ => {
cx.emit_err(session_diagnostics::UnknownMetaItem {
span: param.span(),
item: param.path().to_string(),
expected: &["feature", "reason", "issue", "soft", "implied_by"],
expected: &["feature", "reason", "issue", "soft", "implied_by", "old_name"],
});
return None;
}
@@ -375,6 +377,7 @@ pub(crate) fn parse_unstability(
issue: issue_num,
is_soft,
implied_by,
old_name,
};
Some((feature, level))
}

View File

@@ -12,7 +12,7 @@ pub mod lib_features {
#[derive(HashStable, TyEncodable, TyDecodable)]
pub enum FeatureStability {
AcceptedSince(Symbol),
Unstable,
Unstable { old_name: Option<Symbol> },
}
#[derive(HashStable, Debug, Default)]

View File

@@ -411,7 +411,7 @@ impl<'tcx> TyCtxt<'tcx> {
match stability {
Some(Stability {
level: attrs::StabilityLevel::Unstable { reason, issue, is_soft, implied_by },
level: attrs::StabilityLevel::Unstable { reason, issue, is_soft, implied_by, .. },
feature,
..
}) => {

View File

@@ -748,6 +748,9 @@ passes_unknown_external_lang_item =
passes_unknown_feature =
unknown feature `{$feature}`
passes_unknown_feature_alias =
feature `{$alias}` has been renamed to `{$feature}`
passes_unknown_lang_item =
definition of an unknown lang item: `{$name}`
.label = definition of unknown lang item `{$name}`

View File

@@ -1560,6 +1560,15 @@ pub(crate) struct UnknownFeature {
pub feature: Symbol,
}
#[derive(Diagnostic)]
#[diag(passes_unknown_feature_alias, code = E0635)]
pub(crate) struct RenamedFeature {
#[primary_span]
pub span: Span,
pub feature: Symbol,
pub alias: Symbol,
}
#[derive(Diagnostic)]
#[diag(passes_implied_feature_not_exist)]
pub(crate) struct ImpliedFeatureNotExist {

View File

@@ -40,7 +40,7 @@ impl<'tcx> LibFeatureCollector<'tcx> {
};
let feature_stability = match level {
StabilityLevel::Unstable { .. } => FeatureStability::Unstable,
StabilityLevel::Unstable { old_name, .. } => FeatureStability::Unstable { old_name },
StabilityLevel::Stable { since, .. } => FeatureStability::AcceptedSince(match since {
StableSince::Version(v) => Symbol::intern(&v.to_string()),
StableSince::Current => sym::env_CFG_RELEASE,
@@ -71,7 +71,7 @@ impl<'tcx> LibFeatureCollector<'tcx> {
});
}
}
(FeatureStability::AcceptedSince(_), Some((FeatureStability::Unstable, _))) => {
(FeatureStability::AcceptedSince(_), Some((FeatureStability::Unstable { .. }, _))) => {
self.tcx.dcx().emit_err(FeaturePreviouslyDeclared {
span,
feature,
@@ -79,7 +79,7 @@ impl<'tcx> LibFeatureCollector<'tcx> {
prev_declared: "unstable",
});
}
(FeatureStability::Unstable, Some((FeatureStability::AcceptedSince(_), _))) => {
(FeatureStability::Unstable { .. }, Some((FeatureStability::AcceptedSince(_), _))) => {
self.tcx.dcx().emit_err(FeaturePreviouslyDeclared {
span,
feature,
@@ -88,7 +88,7 @@ impl<'tcx> LibFeatureCollector<'tcx> {
});
}
// duplicate `unstable` feature is ok.
(FeatureStability::Unstable, Some((FeatureStability::Unstable, _))) => {}
(FeatureStability::Unstable { .. }, Some((FeatureStability::Unstable { .. }, _))) => {}
}
}
}

View File

@@ -718,6 +718,7 @@ fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index {
issue: NonZero::new(27812),
is_soft: false,
implied_by: None,
old_name: None,
},
feature: sym::rustc_private,
};
@@ -1161,8 +1162,8 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
defined_features: &LibFeatures,
all_implications: &UnordMap<Symbol, Symbol>,
) {
for (feature, since) in defined_features.to_sorted_vec() {
if let FeatureStability::AcceptedSince(since) = since
for (feature, stability) in defined_features.to_sorted_vec() {
if let FeatureStability::AcceptedSince(since) = stability
&& let Some(span) = remaining_lib_features.get(&feature)
{
// Warn if the user has enabled an already-stable lib feature.
@@ -1181,6 +1182,12 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) {
// implications from this crate.
remaining_implications.remove(&feature);
if let FeatureStability::Unstable { old_name: Some(alias) } = stability {
if let Some(span) = remaining_lib_features.swap_remove(&alias) {
tcx.dcx().emit_err(errors::RenamedFeature { span, feature, alias });
}
}
if remaining_lib_features.is_empty() && remaining_implications.is_empty() {
break;
}

View File

@@ -974,7 +974,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
) {
let span = path.span;
if let Some(stability) = &ext.stability {
if let StabilityLevel::Unstable { reason, issue, is_soft, implied_by } = stability.level
if let StabilityLevel::Unstable { reason, issue, is_soft, implied_by, .. } =
stability.level
{
let feature = stability.feature;

View File

@@ -1496,6 +1496,7 @@ symbols! {
offset_of_nested,
offset_of_slice,
ok_or_else,
old_name,
omit_gdb_pretty_printer_section,
on,
on_unimplemented,

View File

@@ -98,7 +98,7 @@ pub enum ControlFlow<B, C = ()> {
// is a no-op conversion in the `Try` implementation.
}
#[unstable(feature = "try_trait_v2", issue = "84277")]
#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
impl<B, C> ops::Try for ControlFlow<B, C> {
type Output = C;
type Residual = ControlFlow<B, convert::Infallible>;
@@ -117,7 +117,7 @@ impl<B, C> ops::Try for ControlFlow<B, C> {
}
}
#[unstable(feature = "try_trait_v2", issue = "84277")]
#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
// Note: manually specifying the residual type instead of using the default to work around
// https://github.com/rust-lang/rust/issues/99940
impl<B, C> ops::FromResidual<ControlFlow<B, convert::Infallible>> for ControlFlow<B, C> {

View File

@@ -194,7 +194,7 @@ pub use self::try_trait::Residual;
#[unstable(feature = "try_trait_v2_yeet", issue = "96374")]
pub use self::try_trait::Yeet;
pub(crate) use self::try_trait::{ChangeOutputType, NeverShortCircuit};
#[unstable(feature = "try_trait_v2", issue = "84277")]
#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
pub use self::try_trait::{FromResidual, Try};
#[unstable(feature = "coerce_unsized", issue = "18598")]
pub use self::unsize::CoerceUnsized;

View File

@@ -112,7 +112,7 @@ use crate::ops::ControlFlow;
/// R::from_output(accum)
/// }
/// ```
#[unstable(feature = "try_trait_v2", issue = "84277")]
#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
#[rustc_on_unimplemented(
on(
all(from_desugaring = "TryBlock"),
@@ -130,7 +130,7 @@ use crate::ops::ControlFlow;
#[lang = "Try"]
pub trait Try: FromResidual {
/// The type of the value produced by `?` when *not* short-circuiting.
#[unstable(feature = "try_trait_v2", issue = "84277")]
#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
type Output;
/// The type of the value passed to [`FromResidual::from_residual`]
@@ -154,7 +154,7 @@ pub trait Try: FromResidual {
/// then typically you can use `Foo<std::convert::Infallible>` as its `Residual`
/// type: that type will have a "hole" in the correct place, and will maintain the
/// "foo-ness" of the residual so other types need to opt-in to interconversion.
#[unstable(feature = "try_trait_v2", issue = "84277")]
#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
type Residual;
/// Constructs the type from its `Output` type.
@@ -186,7 +186,7 @@ pub trait Try: FromResidual {
/// assert_eq!(r, Some(4));
/// ```
#[lang = "from_output"]
#[unstable(feature = "try_trait_v2", issue = "84277")]
#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
fn from_output(output: Self::Output) -> Self;
/// Used in `?` to decide whether the operator should produce a value
@@ -213,7 +213,7 @@ pub trait Try: FromResidual {
/// );
/// ```
#[lang = "branch"]
#[unstable(feature = "try_trait_v2", issue = "84277")]
#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
fn branch(self) -> ControlFlow<Self::Residual, Self::Output>;
}
@@ -303,7 +303,7 @@ pub trait Try: FromResidual {
),
)]
#[rustc_diagnostic_item = "FromResidual"]
#[unstable(feature = "try_trait_v2", issue = "84277")]
#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
pub trait FromResidual<R = <Self as Try>::Residual> {
/// Constructs the type from a compatible `Residual` type.
///
@@ -326,7 +326,7 @@ pub trait FromResidual<R = <Self as Try>::Residual> {
/// );
/// ```
#[lang = "from_residual"]
#[unstable(feature = "try_trait_v2", issue = "84277")]
#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
fn from_residual(residual: R) -> Self;
}

View File

@@ -2532,7 +2532,7 @@ impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> {
}
}
#[unstable(feature = "try_trait_v2", issue = "84277")]
#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
impl<T> ops::Try for Option<T> {
type Output = T;
type Residual = Option<convert::Infallible>;
@@ -2551,7 +2551,7 @@ impl<T> ops::Try for Option<T> {
}
}
#[unstable(feature = "try_trait_v2", issue = "84277")]
#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
// Note: manually specifying the residual type instead of using the default to work around
// https://github.com/rust-lang/rust/issues/99940
impl<T> ops::FromResidual<Option<convert::Infallible>> for Option<T> {

View File

@@ -2051,7 +2051,7 @@ impl<A, E, V: FromIterator<A>> FromIterator<Result<A, E>> for Result<V, E> {
}
}
#[unstable(feature = "try_trait_v2", issue = "84277")]
#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
impl<T, E> ops::Try for Result<T, E> {
type Output = T;
type Residual = Result<convert::Infallible, E>;
@@ -2070,7 +2070,7 @@ impl<T, E> ops::Try for Result<T, E> {
}
}
#[unstable(feature = "try_trait_v2", issue = "84277")]
#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
impl<T, E, F: From<E>> ops::FromResidual<Result<convert::Infallible, E>> for Result<T, F> {
#[inline]
#[track_caller]

View File

@@ -229,7 +229,7 @@ impl<T> From<T> for Poll<T> {
}
}
#[unstable(feature = "try_trait_v2", issue = "84277")]
#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
impl<T, E> ops::Try for Poll<Result<T, E>> {
type Output = Poll<T>;
type Residual = Result<convert::Infallible, E>;
@@ -249,7 +249,7 @@ impl<T, E> ops::Try for Poll<Result<T, E>> {
}
}
#[unstable(feature = "try_trait_v2", issue = "84277")]
#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
impl<T, E, F: From<E>> ops::FromResidual<Result<convert::Infallible, E>> for Poll<Result<T, F>> {
#[inline]
fn from_residual(x: Result<convert::Infallible, E>) -> Self {
@@ -259,7 +259,7 @@ impl<T, E, F: From<E>> ops::FromResidual<Result<convert::Infallible, E>> for Pol
}
}
#[unstable(feature = "try_trait_v2", issue = "84277")]
#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
impl<T, E> ops::Try for Poll<Option<Result<T, E>>> {
type Output = Poll<Option<T>>;
type Residual = Result<convert::Infallible, E>;
@@ -280,7 +280,7 @@ impl<T, E> ops::Try for Poll<Option<Result<T, E>>> {
}
}
#[unstable(feature = "try_trait_v2", issue = "84277")]
#[unstable(feature = "try_trait_v2", issue = "84277", old_name = "try_trait")]
impl<T, E, F: From<E>> ops::FromResidual<Result<convert::Infallible, E>>
for Poll<Option<Result<T, F>>>
{

View File

@@ -2638,7 +2638,7 @@ mod size_asserts {
static_assert_size!(GenericParamDef, 40);
static_assert_size!(Generics, 16);
static_assert_size!(Item, 8);
static_assert_size!(ItemInner, 136);
static_assert_size!(ItemInner, 144);
static_assert_size!(ItemKind, 48);
static_assert_size!(PathSegment, 32);
static_assert_size!(Type, 32);

View File

@@ -1,3 +1,3 @@
#![feature(try_trait)] //~ ERROR unknown feature `try_trait`
#![feature(try_trait)] //~ ERROR feature `try_trait` has been renamed to `try_trait_v2` [E0635]
fn main() {}

View File

@@ -1,4 +1,4 @@
error[E0635]: unknown feature `try_trait`
error[E0635]: feature `try_trait` has been renamed to `try_trait_v2`
--> $DIR/renamed_feature.rs:1:12
|
LL | #![feature(try_trait)]

View File

@@ -82,10 +82,10 @@ hir-stats - Expr 32 (NN.N%) 1
hir-stats - Let 32 (NN.N%) 1
hir-stats - Semi 32 (NN.N%) 1
hir-stats FnDecl 120 (NN.N%) 3 40
hir-stats Attribute 128 (NN.N%) 4 32
hir-stats FieldDef 128 (NN.N%) 2 64
hir-stats GenericArgs 144 (NN.N%) 3 48
hir-stats Variant 144 (NN.N%) 2 72
hir-stats Attribute 160 (NN.N%) 4 40
hir-stats GenericBound 256 (NN.N%) 4 64
hir-stats - Trait 256 (NN.N%) 4
hir-stats Block 288 (NN.N%) 6 48
@@ -117,5 +117,5 @@ hir-stats - Use 352 (NN.N%) 4
hir-stats Path 1_040 (NN.N%) 26 40
hir-stats PathSegment 1_776 (NN.N%) 37 48
hir-stats ----------------------------------------------------------------
hir-stats Total 8_644 172
hir-stats Total 8_676 172
hir-stats