Rollup merge of #154015 - josetorrs:refactor-parse-stability, r=JonathanBrouwer

refactor - moving `check_stability` check to `parse_stability`

This PR is part of issue https://github.com/rust-lang/rust/issues/153101 and by extension this https://github.com/rust-lang/rust/issues/131229 as well

r? @JonathanBrouwer
This commit is contained in:
Jonathan Brouwer
2026-03-20 19:36:21 +01:00
committed by GitHub
4 changed files with 27 additions and 46 deletions
@@ -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,
@@ -366,7 +367,7 @@ pub(crate) fn parse_stability<S: Stage>(
}
}
// 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<S: Stage>(
cx: &AcceptContext<'_, '_, S>,
@@ -451,6 +452,16 @@ pub(crate) fn parse_unstability<S: Stage>(
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,
item_span: cx.target_span,
});
return None;
}
let level = StabilityLevel::Unstable {
reason: UnstableReason::from_opt_reason(reason),
issue: issue_num,
@@ -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,
}
+4 -34
View File
@@ -16,10 +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::{
ACCEPTED_LANG_FEATURES, 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,
@@ -30,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,16 +152,6 @@ fn check_attributes(
Attribute::Parsed(AttributeKind::ProcMacroDerive { .. }) => {
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, .. },
},
) => 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)
@@ -312,6 +298,7 @@ fn check_attributes(
| AttributeKind::RustcCoherenceIsCore(..)
| AttributeKind::RustcCoinductive(..)
| AttributeKind::RustcConfusables { .. }
| AttributeKind::RustcConstStability { .. }
| AttributeKind::RustcConstStableIndirect
| AttributeKind::RustcConversionSuggestion
| AttributeKind::RustcDeallocator
@@ -384,6 +371,7 @@ fn check_attributes(
| AttributeKind::RustcTrivialFieldReads
| AttributeKind::RustcUnsafeSpecializationMarker(..)
| AttributeKind::ShouldPanic { .. }
| AttributeKind::Stability { .. }
| AttributeKind::TestRunner(..)
| AttributeKind::ThreadLocal
| AttributeKind::TypeLengthLimit { .. }
@@ -1570,24 +1558,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
-11
View File
@@ -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> {