From ed6a6fddb440f2b19d55530a07df0c7c94391ad8 Mon Sep 17 00:00:00 2001 From: Jose Date: Fri, 13 Mar 2026 14:43:44 -0400 Subject: [PATCH 1/4] refactoring stability check --- .../src/attributes/stability.rs | 11 ++++++++ compiler/rustc_passes/src/check_attr.rs | 25 ++----------------- 2 files changed, 13 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index 6ddd9f2c1fb5..f9e3f41a46fe 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -1,6 +1,7 @@ use std::num::NonZero; use rustc_errors::ErrorGuaranteed; +use rustc_feature::ACCEPTED_LANG_FEATURES; use rustc_hir::target::GenericParamKind; use rustc_hir::{ DefaultBodyStability, MethodKind, PartialConstStability, Stability, StabilityLevel, @@ -451,6 +452,16 @@ pub(crate) fn parse_unstability( match (feature, issue) { (Ok(feature), Ok(_)) => { + // Validate that unstable attributes don't use already-stable language features + + if ACCEPTED_LANG_FEATURES.iter().any(|f| f.name == feature) { + cx.emit_err(session_diagnostics::UnstableAttrForAlreadyStableFeature { + attr_span: cx.attr_span, + item_span: cx.target_span, + }); + return None; + } + let level = StabilityLevel::Unstable { reason: UnstableReason::from_opt_reason(reason), issue: issue_num, diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 9945802d70c1..9ab780e88439 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -17,8 +17,7 @@ use rustc_data_structures::unord::UnordMap; use rustc_errors::{DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey, msg}; use rustc_feature::{ - ACCEPTED_LANG_FEATURES, AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP, - BuiltinAttribute, + AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute, }; use rustc_hir::attrs::diagnostic::Directive; use rustc_hir::attrs::{ @@ -165,7 +164,7 @@ fn check_attributes( span: attr_span, stability: PartialConstStability { level, feature, .. }, }, - ) => self.check_stability(*attr_span, span, level, *feature), + ) => {} Attribute::Parsed(AttributeKind::Inline(InlineAttr::Force { .. }, ..)) => {} // handled separately below Attribute::Parsed(AttributeKind::Inline(kind, attr_span)) => { self.check_inline(hir_id, *attr_span, kind, target) @@ -1551,8 +1550,6 @@ fn check_macro_only_attr( } } - /// Outputs an error for `#[allow_internal_unstable]` which can only be applied to macros. - /// (Allows proc_macro functions) fn check_rustc_allow_const_fn_unstable( &self, hir_id: HirId, @@ -1570,24 +1567,6 @@ fn check_rustc_allow_const_fn_unstable( } } - fn check_stability( - &self, - attr_span: Span, - item_span: Span, - level: &StabilityLevel, - feature: Symbol, - ) { - // Stable *language* features shouldn't be used as unstable library features. - // (Not doing this for stable library features is checked by tidy.) - if level.is_unstable() - && ACCEPTED_LANG_FEATURES.iter().find(|f| f.name == feature).is_some() - { - self.tcx - .dcx() - .emit_err(errors::UnstableAttrForAlreadyStableFeature { attr_span, item_span }); - } - } - fn check_deprecated(&self, hir_id: HirId, attr_span: Span, target: Target) { match target { Target::AssocConst | Target::Method(..) | Target::AssocTy From c614e3d216b26052d0badfeb5c33f095b4ced1f3 Mon Sep 17 00:00:00 2001 From: Jose Date: Fri, 13 Mar 2026 16:38:15 -0400 Subject: [PATCH 2/4] linting, moving error to session diagnostics --- .../src/attributes/stability.rs | 4 +--- .../src/session_diagnostics.rs | 11 +++++++++++ compiler/rustc_passes/src/check_attr.rs | 17 ++++------------- compiler/rustc_passes/src/errors.rs | 11 ----------- 4 files changed, 16 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index f9e3f41a46fe..8aa013ec4108 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -452,8 +452,6 @@ pub(crate) fn parse_unstability( match (feature, issue) { (Ok(feature), Ok(_)) => { - // Validate that unstable attributes don't use already-stable language features - if ACCEPTED_LANG_FEATURES.iter().any(|f| f.name == feature) { cx.emit_err(session_diagnostics::UnstableAttrForAlreadyStableFeature { attr_span: cx.attr_span, @@ -461,7 +459,7 @@ pub(crate) fn parse_unstability( }); return None; } - + let level = StabilityLevel::Unstable { reason: UnstableReason::from_opt_reason(reason), issue: issue_num, diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 069488948868..bab830098f1a 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -1046,3 +1046,14 @@ pub(crate) struct CustomMirIncompatibleDialectAndPhase { #[label("... is not compatible with this phase")] pub phase_span: Span, } + +#[derive(Diagnostic)] +#[diag("can't mark as unstable using an already stable feature")] +pub(crate) struct UnstableAttrForAlreadyStableFeature { + #[primary_span] + #[label("this feature is already stable")] + #[help("consider removing the attribute")] + pub attr_span: Span, + #[label("the stability attribute annotates this item")] + pub item_span: Span, +} diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 9ab780e88439..4f11215aaa31 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -16,9 +16,7 @@ use rustc_data_structures::thin_vec::ThinVec; use rustc_data_structures::unord::UnordMap; use rustc_errors::{DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey, msg}; -use rustc_feature::{ - AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute, -}; +use rustc_feature::{AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute}; use rustc_hir::attrs::diagnostic::Directive; use rustc_hir::attrs::{ AttributeKind, DocAttribute, DocInline, EiiDecl, EiiImpl, EiiImplResolution, InlineAttr, @@ -29,8 +27,7 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{ self as hir, Attribute, CRATE_HIR_ID, Constness, FnSig, ForeignItem, GenericParamKind, HirId, - Item, ItemKind, MethodKind, Node, ParamName, PartialConstStability, Safety, Stability, - StabilityLevel, Target, TraitItem, find_attr, + Item, ItemKind, MethodKind, Node, ParamName, Safety, Target, TraitItem, find_attr, }; use rustc_macros::Diagnostic; use rustc_middle::hir::nested_filter; @@ -156,14 +153,8 @@ fn check_attributes( self.check_proc_macro(hir_id, target, ProcMacroKind::Derive) } Attribute::Parsed( - AttributeKind::Stability { - span: attr_span, - stability: Stability { level, feature }, - } - | AttributeKind::RustcConstStability { - span: attr_span, - stability: PartialConstStability { level, feature, .. }, - }, + AttributeKind::Stability { .. } + | AttributeKind::RustcConstStability { .. }, ) => {} Attribute::Parsed(AttributeKind::Inline(InlineAttr::Force { .. }, ..)) => {} // handled separately below Attribute::Parsed(AttributeKind::Inline(kind, attr_span)) => { diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 6efbcd7bf85b..5e84122fcb10 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -871,17 +871,6 @@ pub(crate) struct CannotStabilizeDeprecated { pub item_sp: Span, } -#[derive(Diagnostic)] -#[diag("can't mark as unstable using an already stable feature")] -pub(crate) struct UnstableAttrForAlreadyStableFeature { - #[primary_span] - #[label("this feature is already stable")] - #[help("consider removing the attribute")] - pub attr_span: Span, - #[label("the stability attribute annotates this item")] - pub item_span: Span, -} - #[derive(Diagnostic)] #[diag("{$descr} has missing stability attribute")] pub(crate) struct MissingStabilityAttr<'a> { From 4e446d55a40cae05284fc4118b18373e7dd71f02 Mon Sep 17 00:00:00 2001 From: Jose Date: Tue, 17 Mar 2026 16:53:54 -0400 Subject: [PATCH 3/4] restore code comment --- compiler/rustc_attr_parsing/src/attributes/stability.rs | 2 ++ compiler/rustc_passes/src/check_attr.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index 8aa013ec4108..a5e9a070c562 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -452,6 +452,8 @@ pub(crate) fn parse_unstability( match (feature, issue) { (Ok(feature), Ok(_)) => { + // Stable *language* features shouldn't be used as unstable library features. + // (Not doing this for stable library features is checked by tidy.) if ACCEPTED_LANG_FEATURES.iter().any(|f| f.name == feature) { cx.emit_err(session_diagnostics::UnstableAttrForAlreadyStableFeature { attr_span: cx.attr_span, diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 4f11215aaa31..3433eaca3e1d 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1541,6 +1541,8 @@ fn check_macro_only_attr( } } + /// Outputs an error for `#[allow_internal_unstable]` which can only be applied to macros. + /// (Allows proc_macro functions) fn check_rustc_allow_const_fn_unstable( &self, hir_id: HirId, From 3ea7d1ece76c0d207f3c7754140b07c2b7f5e549 Mon Sep 17 00:00:00 2001 From: Jose Torres Date: Fri, 20 Mar 2026 12:14:41 -0400 Subject: [PATCH 4/4] fixing seperate empty arm and doc comment --- compiler/rustc_attr_parsing/src/attributes/stability.rs | 2 +- compiler/rustc_passes/src/check_attr.rs | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index a5e9a070c562..25b295c162aa 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -367,7 +367,7 @@ pub(crate) fn parse_stability( } } -// Read the content of a `unstable`/`rustc_const_unstable`/`rustc_default_body_unstable` +/// Read the content of a `unstable`/`rustc_const_unstable`/`rustc_default_body_unstable` /// attribute, and return the feature name and its stability information. pub(crate) fn parse_unstability( cx: &AcceptContext<'_, '_, S>, diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 3433eaca3e1d..a8ca8011b571 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -152,10 +152,6 @@ fn check_attributes( Attribute::Parsed(AttributeKind::ProcMacroDerive { .. }) => { self.check_proc_macro(hir_id, target, ProcMacroKind::Derive) } - Attribute::Parsed( - AttributeKind::Stability { .. } - | AttributeKind::RustcConstStability { .. }, - ) => {} Attribute::Parsed(AttributeKind::Inline(InlineAttr::Force { .. }, ..)) => {} // handled separately below Attribute::Parsed(AttributeKind::Inline(kind, attr_span)) => { self.check_inline(hir_id, *attr_span, kind, target) @@ -302,6 +298,7 @@ fn check_attributes( | AttributeKind::RustcCoherenceIsCore(..) | AttributeKind::RustcCoinductive(..) | AttributeKind::RustcConfusables { .. } + | AttributeKind::RustcConstStability { .. } | AttributeKind::RustcConstStableIndirect | AttributeKind::RustcConversionSuggestion | AttributeKind::RustcDeallocator @@ -374,6 +371,7 @@ fn check_attributes( | AttributeKind::RustcTrivialFieldReads | AttributeKind::RustcUnsafeSpecializationMarker(..) | AttributeKind::ShouldPanic { .. } + | AttributeKind::Stability { .. } | AttributeKind::TestRunner(..) | AttributeKind::ThreadLocal | AttributeKind::TypeLengthLimit { .. }