From ee15bd5fe0f67cd350bf9bced0bf6a65e40e603a Mon Sep 17 00:00:00 2001 From: CastilloDel Date: Fri, 11 Oct 2024 22:05:58 +0200 Subject: [PATCH] Emit an error for unstable attributes that reference already stable features --- compiler/rustc_passes/messages.ftl | 6 ++++++ compiler/rustc_passes/src/errors.rs | 11 +++++++++++ compiler/rustc_passes/src/stability.rs | 16 ++++++++++++++++ ...-attribute-rejects-already-stable-features.rs | 11 +++++++++++ 4 files changed, 44 insertions(+) create mode 100644 tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.rs diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 5369f54afb908..737e4e14a537b 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -745,6 +745,12 @@ passes_unrecognized_repr_hint = unrecognized representation hint .help = valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` +passes_unstable_attr_for_already_stable_feature = + can't mark as unstable using an already stable feature + .label = this feature is already stable + .item = the stability attribute annotates this item + .help = Consider removing the attribute + passes_unused = unused attribute .suggestion = remove this attribute diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 29a087bf75975..021145aff7cfe 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1496,6 +1496,17 @@ pub(crate) struct CannotStabilizeDeprecated { pub item_sp: Span, } +#[derive(Diagnostic)] +#[diag(passes_unstable_attr_for_already_stable_feature)] +pub(crate) struct UnstableAttrForAlreadyStableFeature { + #[primary_span] + #[label] + #[help] + pub span: Span, + #[label(passes_item)] + pub item_sp: Span, +} + #[derive(Diagnostic)] #[diag(passes_missing_stability_attr)] pub(crate) struct MissingStabilityAttr<'a> { diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 46b67e930d5e9..751c87a9fe519 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -10,6 +10,7 @@ use rustc_attr::{ }; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::unord::{ExtendUnord, UnordMap, UnordSet}; +use rustc_feature::ACCEPTED_FEATURES; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalModDefId}; @@ -246,12 +247,27 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { } } + if let Stability { level: Unstable { .. }, feature } = stab { + if ACCEPTED_FEATURES.iter().find(|f| f.name == feature).is_some() { + self.tcx + .dcx() + .emit_err(errors::UnstableAttrForAlreadyStableFeature { span, item_sp }); + } + } if let Stability { level: Unstable { implied_by: Some(implied_by), .. }, feature } = stab { self.index.implications.insert(implied_by, feature); } + if let Some(ConstStability { level: Unstable { .. }, feature, .. }) = const_stab { + if ACCEPTED_FEATURES.iter().find(|f| f.name == feature).is_some() { + self.tcx.dcx().emit_err(errors::UnstableAttrForAlreadyStableFeature { + span: const_span.unwrap(), // If const_stab contains Some(..), same is true for const_span + item_sp, + }); + } + } if let Some(ConstStability { level: Unstable { implied_by: Some(implied_by), .. }, feature, diff --git a/tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.rs b/tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.rs new file mode 100644 index 0000000000000..8964be19b5300 --- /dev/null +++ b/tests/ui/feature-gates/unstable-attribute-rejects-already-stable-features.rs @@ -0,0 +1,11 @@ +//! Ensure #[unstable] doesn't accept already stable features +//@ check-fail + +#![feature(staged_api)] +#![stable(feature = "rust_test", since = "1.0.0")] + +#[unstable(feature = "arbitrary_enum_discriminant", issue = "42")] +#[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")] +const fn my_fun() {} + +fn main() {}