Skip to content

Commit f12e677

Browse files
committed
Refactor stability structs
This moves stability structs' `feature` fields into `StabilityLevel::Unstable` and `ConstStabilityLevel::Unstable`, in preparation to support multiple unstable attributes on items. Seemingly, the `feature` field isn't used with the `StabilityLevel::Stable` variant, so I haven't included it. `rustc_passes::lib_features` uses the 'feature' meta-item for 'stable' attributes, but it extracts them itself, rather than relying on `rustc_attr`.
1 parent 917a50a commit f12e677

File tree

5 files changed

+76
-95
lines changed

5 files changed

+76
-95
lines changed

compiler/rustc_attr/src/builtin.rs

Lines changed: 49 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,6 @@ pub enum OptimizeAttr {
7070
#[derive(HashStable_Generic)]
7171
pub struct Stability {
7272
pub level: StabilityLevel,
73-
pub feature: Symbol,
7473
}
7574

7675
impl Stability {
@@ -88,11 +87,11 @@ impl Stability {
8887
}
8988

9089
/// Represents the `#[rustc_const_unstable]` and `#[rustc_const_stable]` attributes.
90+
/// For details see [the dev guide](https://rustc-dev-guide.rust-lang.org/stability.html#rustc_const_unstable).
9191
#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
9292
#[derive(HashStable_Generic)]
9393
pub struct ConstStability {
9494
pub level: StabilityLevel,
95-
pub feature: Symbol,
9695
/// This is true iff the `const_stable_indirect` attribute is present.
9796
pub const_stable_indirect: bool,
9897
/// whether the function has a `#[rustc_promotable]` attribute
@@ -114,7 +113,6 @@ impl ConstStability {
114113
#[derive(HashStable_Generic)]
115114
pub struct DefaultBodyStability {
116115
pub level: StabilityLevel,
117-
pub feature: Symbol,
118116
}
119117

120118
/// The available stability levels.
@@ -123,31 +121,11 @@ pub struct DefaultBodyStability {
123121
pub enum StabilityLevel {
124122
/// `#[unstable]`
125123
Unstable {
124+
/// The information unique to each `#[unstable]` attribute
125+
unstables: Unstability,
126126
/// Reason for the current stability level.
127127
reason: UnstableReason,
128-
/// Relevant `rust-lang/rust` issue.
129-
issue: Option<NonZero<u32>>,
130128
is_soft: bool,
131-
/// If part of a feature is stabilized and a new feature is added for the remaining parts,
132-
/// then the `implied_by` attribute is used to indicate which now-stable feature previously
133-
/// contained an item.
134-
///
135-
/// ```pseudo-Rust
136-
/// #[unstable(feature = "foo", issue = "...")]
137-
/// fn foo() {}
138-
/// #[unstable(feature = "foo", issue = "...")]
139-
/// fn foobar() {}
140-
/// ```
141-
///
142-
/// ...becomes...
143-
///
144-
/// ```pseudo-Rust
145-
/// #[stable(feature = "foo", since = "1.XX.X")]
146-
/// fn foo() {}
147-
/// #[unstable(feature = "foobar", issue = "...", implied_by = "foo")]
148-
/// fn foobar() {}
149-
/// ```
150-
implied_by: Option<Symbol>,
151129
},
152130
/// `#[stable]`
153131
Stable {
@@ -185,6 +163,35 @@ impl StabilityLevel {
185163
}
186164
}
187165

166+
/// An instance of an `#[unstable]`, `#[rustc_const_unstable]`, or similar attribute
167+
#[derive(Encodable, Decodable, PartialEq, Copy, Clone, Debug, Eq, Hash)]
168+
#[derive(HashStable_Generic)]
169+
pub struct Unstability {
170+
pub feature: Symbol,
171+
/// Relevant `rust-lang/rust` issue.
172+
pub issue: Option<NonZero<u32>>,
173+
/// If part of a feature is stabilized and a new feature is added for the remaining parts,
174+
/// then the `implied_by` attribute is used to indicate which now-stable feature previously
175+
/// contained an item.
176+
///
177+
/// ```pseudo-Rust
178+
/// #[unstable(feature = "foo", issue = "...")]
179+
/// fn foo() {}
180+
/// #[unstable(feature = "foo", issue = "...")]
181+
/// fn foobar() {}
182+
/// ```
183+
///
184+
/// ...becomes...
185+
///
186+
/// ```pseudo-Rust
187+
/// #[stable(feature = "foo", since = "1.XX.X")]
188+
/// fn foo() {}
189+
/// #[unstable(feature = "foobar", issue = "...", implied_by = "foo")]
190+
/// fn foobar() {}
191+
/// ```
192+
pub implied_by: Option<Symbol>,
193+
}
194+
188195
#[derive(Encodable, Decodable, PartialEq, Copy, Clone, Debug, Eq, Hash)]
189196
#[derive(HashStable_Generic)]
190197
pub enum UnstableReason {
@@ -231,8 +238,8 @@ pub fn find_stability(
231238
break;
232239
}
233240

234-
if let Some((feature, level)) = parse_unstability(sess, attr) {
235-
stab = Some((Stability { level, feature }, attr.span));
241+
if let Some(level) = parse_unstability(sess, attr) {
242+
stab = Some((Stability { level }, attr.span));
236243
}
237244
}
238245
sym::stable => {
@@ -241,8 +248,8 @@ pub fn find_stability(
241248
.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span });
242249
break;
243250
}
244-
if let Some((feature, level)) = parse_stability(sess, attr) {
245-
stab = Some((Stability { level, feature }, attr.span));
251+
if let Some(level) = parse_stability(sess, attr) {
252+
stab = Some((Stability { level }, attr.span));
246253
}
247254
}
248255
_ => {}
@@ -290,14 +297,9 @@ pub fn find_const_stability(
290297
break;
291298
}
292299

293-
if let Some((feature, level)) = parse_unstability(sess, attr) {
300+
if let Some(level) = parse_unstability(sess, attr) {
294301
const_stab = Some((
295-
ConstStability {
296-
level,
297-
feature,
298-
const_stable_indirect: false,
299-
promotable: false,
300-
},
302+
ConstStability { level, const_stable_indirect: false, promotable: false },
301303
attr.span,
302304
));
303305
}
@@ -308,14 +310,9 @@ pub fn find_const_stability(
308310
.emit_err(session_diagnostics::MultipleStabilityLevels { span: attr.span });
309311
break;
310312
}
311-
if let Some((feature, level)) = parse_stability(sess, attr) {
313+
if let Some(level) = parse_stability(sess, attr) {
312314
const_stab = Some((
313-
ConstStability {
314-
level,
315-
feature,
316-
const_stable_indirect: false,
317-
promotable: false,
318-
},
315+
ConstStability { level, const_stable_indirect: false, promotable: false },
319316
attr.span,
320317
));
321318
}
@@ -369,12 +366,7 @@ pub fn unmarked_crate_const_stab(
369366
// We enforce recursive const stability rules for those functions.
370367
let const_stable_indirect =
371368
attrs.iter().any(|a| a.name_or_empty() == sym::rustc_const_stable_indirect);
372-
ConstStability {
373-
feature: regular_stab.feature,
374-
const_stable_indirect,
375-
promotable: false,
376-
level: regular_stab.level,
377-
}
369+
ConstStability { const_stable_indirect, promotable: false, level: regular_stab.level }
378370
}
379371

380372
/// Collects stability info from `rustc_default_body_unstable` attributes in `attrs`.
@@ -393,8 +385,8 @@ pub fn find_body_stability(
393385
break;
394386
}
395387

396-
if let Some((feature, level)) = parse_unstability(sess, attr) {
397-
body_stab = Some((DefaultBodyStability { level, feature }, attr.span));
388+
if let Some(level) = parse_unstability(sess, attr) {
389+
body_stab = Some((DefaultBodyStability { level }, attr.span));
398390
}
399391
}
400392
}
@@ -420,7 +412,7 @@ fn insert_or_error(sess: &Session, meta: &MetaItem, item: &mut Option<Symbol>) -
420412

421413
/// Read the content of a `stable`/`rustc_const_stable` attribute, and return the feature name and
422414
/// its stability information.
423-
fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, StabilityLevel)> {
415+
fn parse_stability(sess: &Session, attr: &Attribute) -> Option<StabilityLevel> {
424416
let meta = attr.meta()?;
425417
let MetaItem { kind: MetaItemKind::List(ref metas), .. } = meta else { return None };
426418

@@ -474,17 +466,16 @@ fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabilit
474466
};
475467

476468
match feature {
477-
Ok(feature) => {
478-
let level = StabilityLevel::Stable { since, allowed_through_unstable_modules: false };
479-
Some((feature, level))
469+
Ok(_feature) => {
470+
Some(StabilityLevel::Stable { since, allowed_through_unstable_modules: false })
480471
}
481472
Err(ErrorGuaranteed { .. }) => None,
482473
}
483474
}
484475

485476
/// Read the content of a `unstable`/`rustc_const_unstable`/`rustc_default_body_unstable`
486477
/// attribute, and return the feature name and its stability information.
487-
fn parse_unstability(sess: &Session, attr: &Attribute) -> Option<(Symbol, StabilityLevel)> {
478+
fn parse_unstability(sess: &Session, attr: &Attribute) -> Option<StabilityLevel> {
488479
let meta = attr.meta()?;
489480
let MetaItem { kind: MetaItemKind::List(ref metas), .. } = meta else { return None };
490481

@@ -564,12 +555,11 @@ fn parse_unstability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabil
564555
match (feature, issue) {
565556
(Ok(feature), Ok(_)) => {
566557
let level = StabilityLevel::Unstable {
558+
unstables: Unstability { feature, issue: issue_num, implied_by },
567559
reason: UnstableReason::from_opt_reason(reason),
568-
issue: issue_num,
569560
is_soft,
570-
implied_by,
571561
};
572-
Some((feature, level))
562+
Some(level)
573563
}
574564
(Err(ErrorGuaranteed { .. }), _) | (_, Err(ErrorGuaranteed { .. })) => None,
575565
}

compiler/rustc_const_eval/src/check_consts/check.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::mem;
66
use std::num::NonZero;
77
use std::ops::Deref;
88

9-
use rustc_attr::{ConstStability, StabilityLevel};
9+
use rustc_attr::{ConstStability, StabilityLevel, Unstability};
1010
use rustc_errors::{Diag, ErrorGuaranteed};
1111
use rustc_hir::def_id::DefId;
1212
use rustc_hir::{self as hir, LangItem};
@@ -747,13 +747,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
747747
}
748748
}
749749
Some(ConstStability {
750-
level: StabilityLevel::Unstable { .. },
751-
feature,
750+
level: StabilityLevel::Unstable { unstables, .. },
752751
..
753752
}) => {
754753
self.check_op(ops::IntrinsicUnstable {
755754
name: intrinsic.name,
756-
feature,
755+
feature: unstables.feature,
757756
const_stable_indirect: is_const_stable,
758757
});
759758
}
@@ -799,10 +798,11 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
799798
}
800799
}
801800
Some(ConstStability {
802-
level: StabilityLevel::Unstable { implied_by: implied_feature, issue, .. },
803-
feature,
801+
level: StabilityLevel::Unstable { unstables, .. },
804802
..
805803
}) => {
804+
let Unstability { feature, implied_by: implied_feature, issue, .. } =
805+
unstables;
806806
// An unstable const fn with a feature gate.
807807
let callee_safe_to_expose_on_stable =
808808
is_safe_to_expose_on_stable_const_fn(tcx, callee);

compiler/rustc_middle/src/middle/stability.rs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -413,11 +413,8 @@ impl<'tcx> TyCtxt<'tcx> {
413413
}
414414

415415
match stability {
416-
Some(Stability {
417-
level: attr::Unstable { reason, issue, is_soft, implied_by },
418-
feature,
419-
..
420-
}) => {
416+
Some(Stability { level: attr::Unstable { unstables, reason, is_soft } }) => {
417+
let attr::Unstability { feature, issue, implied_by } = unstables;
421418
if span.allows_unstable(feature) {
422419
debug!("stability: skipping span={:?} since it is internal", span);
423420
return EvalResult::Allow;
@@ -501,10 +498,8 @@ impl<'tcx> TyCtxt<'tcx> {
501498
}
502499

503500
match stability {
504-
Some(DefaultBodyStability {
505-
level: attr::Unstable { reason, issue, is_soft, .. },
506-
feature,
507-
}) => {
501+
Some(DefaultBodyStability { level: attr::Unstable { unstables, reason, is_soft } }) => {
502+
let attr::Unstability { feature, issue, .. } = unstables;
508503
if span.allows_unstable(feature) {
509504
debug!("body stability: skipping span={:?} since it is internal", span);
510505
return EvalResult::Allow;

compiler/rustc_passes/src/stability.rs

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::num::NonZero;
66

77
use rustc_attr::{
88
self as attr, ConstStability, DeprecatedSince, Stability, StabilityLevel, StableSince,
9-
Unstable, UnstableReason, VERSION_PLACEHOLDER,
9+
Unstability, Unstable, UnstableReason, VERSION_PLACEHOLDER,
1010
};
1111
use rustc_data_structures::fx::FxIndexMap;
1212
use rustc_data_structures::unord::{ExtendUnord, UnordMap, UnordSet};
@@ -224,15 +224,15 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
224224

225225
// Stable *language* features shouldn't be used as unstable library features.
226226
// (Not doing this for stable library features is checked by tidy.)
227-
if let Stability { level: Unstable { .. }, feature } = stab {
228-
if ACCEPTED_LANG_FEATURES.iter().find(|f| f.name == feature).is_some() {
227+
if let Unstable { unstables, .. } = stab.level {
228+
if ACCEPTED_LANG_FEATURES.iter().find(|f| f.name == unstables.feature).is_some() {
229229
self.tcx
230230
.dcx()
231231
.emit_err(errors::UnstableAttrForAlreadyStableFeature { span, item_sp });
232232
}
233233
}
234-
if let Stability { level: Unstable { implied_by: Some(implied_by), .. }, feature } =
235-
stab
234+
if let Unstable { unstables, .. } = stab.level
235+
&& let Unstability { feature, implied_by: Some(implied_by), .. } = unstables
236236
{
237237
self.index.implications.insert(implied_by, feature);
238238
}
@@ -278,10 +278,10 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
278278

279279
// Stable *language* features shouldn't be used as unstable library features.
280280
// (Not doing this for stable library features is checked by tidy.)
281-
if let Some((ConstStability { level: Unstable { .. }, feature, .. }, const_span)) =
281+
if let Some((ConstStability { level: Unstable { unstables, .. }, .. }, const_span)) =
282282
const_stab
283283
{
284-
if ACCEPTED_LANG_FEATURES.iter().find(|f| f.name == feature).is_some() {
284+
if ACCEPTED_LANG_FEATURES.iter().find(|f| f.name == unstables.feature).is_some() {
285285
self.tcx.dcx().emit_err(errors::UnstableAttrForAlreadyStableFeature {
286286
span: const_span,
287287
item_sp,
@@ -304,7 +304,6 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
304304
const_stable_indirect: true,
305305
promotable: false,
306306
level: inherit_regular_stab.level,
307-
feature: inherit_regular_stab.feature,
308307
});
309308
}
310309

@@ -313,13 +312,10 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
313312
self.index.const_stab_map.insert(def_id, *const_stab);
314313
});
315314

316-
if let Some(ConstStability {
317-
level: Unstable { implied_by: Some(implied_by), .. },
318-
feature,
319-
..
320-
}) = const_stab
315+
if let Some(ConstStability { level: Unstable { unstables, .. }, .. }) = const_stab
316+
&& let Some(implied_by) = unstables.implied_by
321317
{
322-
self.index.implications.insert(implied_by, feature);
318+
self.index.implications.insert(implied_by, unstables.feature);
323319
}
324320

325321
// `impl const Trait for Type` items forward their const stability to their
@@ -702,12 +698,14 @@ fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index {
702698
if tcx.sess.opts.unstable_opts.force_unstable_if_unmarked {
703699
let stability = Stability {
704700
level: attr::StabilityLevel::Unstable {
701+
unstables: attr::Unstability {
702+
feature: sym::rustc_private,
703+
issue: NonZero::new(27812),
704+
implied_by: None,
705+
},
705706
reason: UnstableReason::Default,
706-
issue: NonZero::new(27812),
707707
is_soft: false,
708-
implied_by: None,
709708
},
710-
feature: sym::rustc_private,
711709
};
712710
annotator.parent_stab = Some(stability);
713711
}

compiler/rustc_resolve/src/macros.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,10 +1003,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
10031003
) {
10041004
let span = path.span;
10051005
if let Some(stability) = &ext.stability {
1006-
if let StabilityLevel::Unstable { reason, issue, is_soft, implied_by } = stability.level
1007-
{
1008-
let feature = stability.feature;
1009-
1006+
if let StabilityLevel::Unstable { unstables, reason, is_soft } = stability.level {
1007+
let rustc_attr::Unstability { feature, issue, implied_by } = unstables;
10101008
let is_allowed =
10111009
|feature| self.tcx.features().enabled(feature) || span.allows_unstable(feature);
10121010
let allowed_by_implication = implied_by.is_some_and(|feature| is_allowed(feature));

0 commit comments

Comments
 (0)