Skip to content

Commit bf8a53e

Browse files
committed
Make feature key optional for rustc_stable, rustc_const_stable attributes
… so partial stabilizations no longer have to make up a feature name that never existed as unstable for the stabilized subset of the API.
1 parent b27ccbc commit bf8a53e

File tree

10 files changed

+49
-41
lines changed

10 files changed

+49
-41
lines changed

compiler/rustc_attr/src/builtin.rs

+22-22
Original file line numberDiff line numberDiff line change
@@ -95,15 +95,13 @@ pub enum OptimizeAttr {
9595
#[derive(HashStable_Generic)]
9696
pub struct Stability {
9797
pub level: StabilityLevel,
98-
pub feature: Symbol,
9998
}
10099

101100
/// Represents the `#[rustc_const_unstable]` and `#[rustc_const_stable]` attributes.
102101
#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
103102
#[derive(HashStable_Generic)]
104103
pub struct ConstStability {
105104
pub level: StabilityLevel,
106-
pub feature: Symbol,
107105
/// whether the function has a `#[rustc_promotable]` attribute
108106
pub promotable: bool,
109107
}
@@ -113,8 +111,18 @@ pub struct ConstStability {
113111
#[derive(HashStable_Generic)]
114112
pub enum StabilityLevel {
115113
// Reason for the current stability level and the relevant rust-lang issue
116-
Unstable { reason: Option<Symbol>, issue: Option<NonZeroU32>, is_soft: bool },
117-
Stable { since: Symbol },
114+
Unstable {
115+
reason: Option<Symbol>,
116+
feature: Symbol,
117+
issue: Option<NonZeroU32>,
118+
is_soft: bool,
119+
},
120+
Stable {
121+
since: Symbol,
122+
// feature flag, should not be set when the feature name remains in use
123+
// for unstable items (i.e. when partially stabilizing a feature)
124+
feature: Option<Symbol>,
125+
},
118126
}
119127

120128
impl StabilityLevel {
@@ -309,14 +317,12 @@ where
309317
);
310318
continue;
311319
}
312-
let level = Unstable { reason, issue: issue_num, is_soft };
320+
let level = Unstable { reason, feature, issue: issue_num, is_soft };
313321
if sym::unstable == meta_name {
314-
stab = Some((Stability { level, feature }, attr.span));
322+
stab = Some((Stability { level }, attr.span));
315323
} else {
316-
const_stab = Some((
317-
ConstStability { level, feature, promotable: false },
318-
attr.span,
319-
));
324+
const_stab =
325+
Some((ConstStability { level, promotable: false }, attr.span));
320326
}
321327
}
322328
(None, _, _) => {
@@ -385,22 +391,16 @@ where
385391
}
386392
}
387393

388-
match (feature, since) {
389-
(Some(feature), Some(since)) => {
390-
let level = Stable { since };
394+
match since {
395+
Some(since) => {
396+
let level = Stable { since, feature };
391397
if sym::stable == meta_name {
392-
stab = Some((Stability { level, feature }, attr.span));
398+
stab = Some((Stability { level }, attr.span));
393399
} else {
394-
const_stab = Some((
395-
ConstStability { level, feature, promotable: false },
396-
attr.span,
397-
));
400+
const_stab =
401+
Some((ConstStability { level, promotable: false }, attr.span));
398402
}
399403
}
400-
(None, _) => {
401-
handle_errors(&sess.parse_sess, attr.span, AttrError::MissingFeature);
402-
continue;
403-
}
404404
_ => {
405405
handle_errors(&sess.parse_sess, attr.span, AttrError::MissingSince);
406406
continue;

compiler/rustc_middle/src/middle/stability.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ impl<'tcx> TyCtxt<'tcx> {
347347

348348
match stability {
349349
Some(&Stability {
350-
level: attr::Unstable { reason, issue, is_soft }, feature, ..
350+
level: attr::Unstable { reason, feature, issue, is_soft }, ..
351351
}) => {
352352
if span.allows_unstable(feature) {
353353
debug!("stability: skipping span={:?} since it is internal", span);

compiler/rustc_mir/src/const_eval/fn_queries.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use rustc_attr::StabilityLevel;
12
use rustc_hir as hir;
23
use rustc_hir::def_id::{DefId, LocalDefId};
34
use rustc_middle::hir::map::blocks::FnLikeNode;
@@ -27,7 +28,11 @@ pub fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
2728
pub fn is_unstable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Symbol> {
2829
if tcx.is_const_fn_raw(def_id) {
2930
let const_stab = tcx.lookup_const_stability(def_id)?;
30-
if const_stab.level.is_unstable() { Some(const_stab.feature) } else { None }
31+
if let StabilityLevel::Unstable { feature, .. } = const_stab.level {
32+
Some(feature)
33+
} else {
34+
None
35+
}
3136
} else {
3237
None
3338
}

compiler/rustc_passes/src/stability.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
231231

232232
// Check if deprecated_since < stable_since. If it is,
233233
// this is *almost surely* an accident.
234-
if let (&Some(dep_since), &attr::Stable { since: stab_since }) =
234+
if let (&Some(dep_since), &attr::Stable { since: stab_since, .. }) =
235235
(&depr.as_ref().and_then(|(d, _)| d.since), &stab.level)
236236
{
237237
// Explicit version of iter::order::lt to handle parse errors properly
@@ -701,10 +701,10 @@ fn stability_index(tcx: TyCtxt<'tcx>, (): ()) -> Index<'tcx> {
701701
let stability = tcx.intern_stability(Stability {
702702
level: attr::StabilityLevel::Unstable {
703703
reason: Some(Symbol::intern(reason)),
704+
feature: sym::rustc_private,
704705
issue: NonZeroU32::new(27812),
705706
is_soft: false,
706707
},
707-
feature: sym::rustc_private,
708708
});
709709
annotator.parent_stab = Some(stability);
710710
}

compiler/rustc_resolve/src/macros.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1141,8 +1141,7 @@ impl<'a> Resolver<'a> {
11411141
) {
11421142
let span = path.span;
11431143
if let Some(stability) = &ext.stability {
1144-
if let StabilityLevel::Unstable { reason, issue, is_soft } = stability.level {
1145-
let feature = stability.feature;
1144+
if let StabilityLevel::Unstable { reason, feature, issue, is_soft } = stability.level {
11461145
if !self.active_features.contains(&feature) && !span.allows_unstable(feature) {
11471146
let lint_buffer = &mut self.lint_buffer;
11481147
let soft_handler =

src/librustdoc/clean/inline.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::iter::once;
44
use std::sync::Arc;
55

66
use rustc_ast as ast;
7+
use rustc_attr::StabilityLevel;
78
use rustc_data_structures::fx::FxHashSet;
89
use rustc_hir as hir;
910
use rustc_hir::def::{DefKind, Res};
@@ -356,7 +357,7 @@ crate fn build_impl(
356357
}
357358

358359
if let Some(stab) = tcx.lookup_stability(did) {
359-
if stab.level.is_unstable() && stab.feature == sym::rustc_private {
360+
if let StabilityLevel::Unstable { feature: sym::rustc_private, .. } = &stab.level {
360361
return;
361362
}
362363
}
@@ -388,7 +389,7 @@ crate fn build_impl(
388389
}
389390

390391
if let Some(stab) = tcx.lookup_stability(did) {
391-
if stab.level.is_unstable() && stab.feature == sym::rustc_private {
392+
if let StabilityLevel::Unstable { feature: sym::rustc_private, .. } = &stab.level {
392393
return;
393394
}
394395
}

src/librustdoc/html/render/mod.rs

+7-5
Original file line numberDiff line numberDiff line change
@@ -640,11 +640,13 @@ fn short_item_info(
640640

641641
// Render unstable items. But don't render "rustc_private" crates (internal compiler crates).
642642
// Those crates are permanently unstable so it makes no sense to render "unstable" everywhere.
643-
if let Some((StabilityLevel::Unstable { reason, issue, .. }, feature)) = item
643+
if let Some(StabilityLevel::Unstable { reason, feature, issue, .. }) = item
644644
.stability(cx.tcx())
645645
.as_ref()
646-
.filter(|stab| stab.feature != sym::rustc_private)
647-
.map(|stab| (stab.level, stab.feature))
646+
.filter(|stab| {
647+
!matches!(stab.level, StabilityLevel::Unstable { feature: sym::rustc_private, .. })
648+
})
649+
.map(|stab| stab.level)
648650
{
649651
let mut message =
650652
"<span class=\"emoji\">🔬</span> This is a nightly-only experimental API.".to_owned();
@@ -801,7 +803,7 @@ fn render_stability_since_raw(
801803

802804
match (ver, const_stability) {
803805
// stable and const stable
804-
(Some(v), Some(ConstStability { level: StabilityLevel::Stable { since }, .. }))
806+
(Some(v), Some(ConstStability { level: StabilityLevel::Stable { since, .. }, .. }))
805807
if Some(since.as_str()).as_deref() != containing_const_ver =>
806808
{
807809
write!(
@@ -813,7 +815,7 @@ fn render_stability_since_raw(
813815
// stable and const unstable
814816
(
815817
Some(v),
816-
Some(ConstStability { level: StabilityLevel::Unstable { issue, .. }, feature, .. }),
818+
Some(ConstStability { level: StabilityLevel::Unstable { issue, feature, .. }, .. }),
817819
) => {
818820
write!(
819821
w,

src/librustdoc/html/render/print_item.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use clean::AttributesExt;
33
use std::cmp::Ordering;
44
use std::fmt;
55

6+
use rustc_attr::StabilityLevel;
67
use rustc_data_structures::fx::FxHashMap;
78
use rustc_hir as hir;
89
use rustc_hir::def::CtorKind;
@@ -414,11 +415,10 @@ fn extra_info_tags(item: &clean::Item, parent: &clean::Item, tcx: TyCtxt<'_>) ->
414415

415416
// The "rustc_private" crates are permanently unstable so it makes no sense
416417
// to render "unstable" everywhere.
417-
if item
418-
.stability(tcx)
419-
.as_ref()
420-
.map(|s| s.level.is_unstable() && s.feature != sym::rustc_private)
421-
== Some(true)
418+
if item.stability(tcx).as_ref().map(|s| {
419+
matches!(s.level, StabilityLevel::Unstable { feature, .. } if feature != sym::rustc_private)
420+
})
421+
== Some(true)
422422
{
423423
tags += &tag_html("unstable", "", "Experimental");
424424
}

src/librustdoc/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#![feature(crate_visibility_modifier)]
1313
#![feature(never_type)]
1414
#![feature(once_cell)]
15+
#![feature(option_result_contains)]
1516
#![feature(type_ascription)]
1617
#![recursion_limit = "256"]
1718
#![warn(rustc::internal)]

src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ fn check_terminator(
368368
fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: Option<&RustcVersion>) -> bool {
369369
rustc_mir::const_eval::is_const_fn(tcx, def_id)
370370
&& tcx.lookup_const_stability(def_id).map_or(true, |const_stab| {
371-
if let rustc_attr::StabilityLevel::Stable { since } = const_stab.level {
371+
if let rustc_attr::StabilityLevel::Stable { since, .. } = const_stab.level {
372372
// Checking MSRV is manually necessary because `rustc` has no such concept. This entire
373373
// function could be removed if `rustc` provided a MSRV-aware version of `is_const_fn`.
374374
// as a part of an unimplemented MSRV check https://github.com/rust-lang/rust/issues/65262.

0 commit comments

Comments
 (0)