Tracking the old name of renamed unstable library attribute
Signed-off-by: xizheyin <xizheyin@smail.nju.edu.cn>
This commit is contained in:
@@ -132,6 +132,7 @@ pub enum StabilityLevel {
|
||||
/// fn foobar() {}
|
||||
/// ```
|
||||
implied_by: Option<Symbol>,
|
||||
old_name: Option<Symbol>,
|
||||
},
|
||||
/// `#[stable]`
|
||||
Stable {
|
||||
|
||||
@@ -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, ¶m, &mut implied_by)?
|
||||
}
|
||||
Some(sym::old_name) => insert_value_into_option_or_error(cx, ¶m, &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))
|
||||
}
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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,
|
||||
..
|
||||
}) => {
|
||||
|
||||
@@ -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}`
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 { .. }, _))) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -1496,6 +1496,7 @@ symbols! {
|
||||
offset_of_nested,
|
||||
offset_of_slice,
|
||||
ok_or_else,
|
||||
old_name,
|
||||
omit_gdb_pretty_printer_section,
|
||||
on,
|
||||
on_unimplemented,
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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>>>
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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() {}
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user