diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 0ab452fb42dc6..87fb11049649f 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -95,7 +95,6 @@ pub enum OptimizeAttr { #[derive(HashStable_Generic)] pub struct Stability { pub level: StabilityLevel, - pub feature: Symbol, } /// Represents the `#[rustc_const_unstable]` and `#[rustc_const_stable]` attributes. @@ -103,7 +102,6 @@ pub struct Stability { #[derive(HashStable_Generic)] pub struct ConstStability { pub level: StabilityLevel, - pub feature: Symbol, /// whether the function has a `#[rustc_promotable]` attribute pub promotable: bool, } @@ -113,8 +111,18 @@ pub struct ConstStability { #[derive(HashStable_Generic)] pub enum StabilityLevel { // Reason for the current stability level and the relevant rust-lang issue - Unstable { reason: Option, issue: Option, is_soft: bool }, - Stable { since: Symbol }, + Unstable { + reason: Option, + feature: Symbol, + issue: Option, + is_soft: bool, + }, + Stable { + since: Symbol, + // feature flag, should not be set when the feature name remains in use + // for unstable items (i.e. when partially stabilizing a feature) + feature: Option, + }, } impl StabilityLevel { @@ -309,14 +317,12 @@ where ); continue; } - let level = Unstable { reason, issue: issue_num, is_soft }; + let level = Unstable { reason, feature, issue: issue_num, is_soft }; if sym::unstable == meta_name { - stab = Some((Stability { level, feature }, attr.span)); + stab = Some((Stability { level }, attr.span)); } else { - const_stab = Some(( - ConstStability { level, feature, promotable: false }, - attr.span, - )); + const_stab = + Some((ConstStability { level, promotable: false }, attr.span)); } } (None, _, _) => { @@ -385,22 +391,16 @@ where } } - match (feature, since) { - (Some(feature), Some(since)) => { - let level = Stable { since }; + match since { + Some(since) => { + let level = Stable { since, feature }; if sym::stable == meta_name { - stab = Some((Stability { level, feature }, attr.span)); + stab = Some((Stability { level }, attr.span)); } else { - const_stab = Some(( - ConstStability { level, feature, promotable: false }, - attr.span, - )); + const_stab = + Some((ConstStability { level, promotable: false }, attr.span)); } } - (None, _) => { - handle_errors(&sess.parse_sess, attr.span, AttrError::MissingFeature); - continue; - } _ => { handle_errors(&sess.parse_sess, attr.span, AttrError::MissingSince); continue; diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index f0b4b6b5a0ca6..94d102de91afc 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -347,7 +347,7 @@ impl<'tcx> TyCtxt<'tcx> { match stability { Some(&Stability { - level: attr::Unstable { reason, issue, is_soft }, feature, .. + level: attr::Unstable { reason, feature, issue, is_soft }, .. }) => { if span.allows_unstable(feature) { debug!("stability: skipping span={:?} since it is internal", span); diff --git a/compiler/rustc_mir/src/const_eval/fn_queries.rs b/compiler/rustc_mir/src/const_eval/fn_queries.rs index 40419a4d201ac..1d0871931f51b 100644 --- a/compiler/rustc_mir/src/const_eval/fn_queries.rs +++ b/compiler/rustc_mir/src/const_eval/fn_queries.rs @@ -1,3 +1,4 @@ +use rustc_attr::StabilityLevel; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::hir::map::blocks::FnLikeNode; @@ -27,7 +28,11 @@ pub fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool { pub fn is_unstable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> Option { if tcx.is_const_fn_raw(def_id) { let const_stab = tcx.lookup_const_stability(def_id)?; - if const_stab.level.is_unstable() { Some(const_stab.feature) } else { None } + if let StabilityLevel::Unstable { feature, .. } = const_stab.level { + Some(feature) + } else { + None + } } else { None } diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index a88393cea8285..6b1315dfb769d 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -231,7 +231,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { // Check if deprecated_since < stable_since. If it is, // this is *almost surely* an accident. - if let (&Some(dep_since), &attr::Stable { since: stab_since }) = + if let (&Some(dep_since), &attr::Stable { since: stab_since, .. }) = (&depr.as_ref().and_then(|(d, _)| d.since), &stab.level) { // Explicit version of iter::order::lt to handle parse errors properly @@ -701,10 +701,10 @@ fn stability_index(tcx: TyCtxt<'tcx>, (): ()) -> Index<'tcx> { let stability = tcx.intern_stability(Stability { level: attr::StabilityLevel::Unstable { reason: Some(Symbol::intern(reason)), + feature: sym::rustc_private, issue: NonZeroU32::new(27812), is_soft: false, }, - feature: sym::rustc_private, }); annotator.parent_stab = Some(stability); } diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 7f86f891c4450..2cb0026ae977a 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -1141,8 +1141,7 @@ impl<'a> Resolver<'a> { ) { let span = path.span; if let Some(stability) = &ext.stability { - if let StabilityLevel::Unstable { reason, issue, is_soft } = stability.level { - let feature = stability.feature; + if let StabilityLevel::Unstable { reason, feature, issue, is_soft } = stability.level { if !self.active_features.contains(&feature) && !span.allows_unstable(feature) { let lint_buffer = &mut self.lint_buffer; let soft_handler = diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 0c81a55843013..c92cbb55f7404 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -4,6 +4,7 @@ use std::iter::once; use std::sync::Arc; use rustc_ast as ast; +use rustc_attr::StabilityLevel; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -356,7 +357,7 @@ crate fn build_impl( } if let Some(stab) = tcx.lookup_stability(did) { - if stab.level.is_unstable() && stab.feature == sym::rustc_private { + if let StabilityLevel::Unstable { feature: sym::rustc_private, .. } = &stab.level { return; } } @@ -388,7 +389,7 @@ crate fn build_impl( } if let Some(stab) = tcx.lookup_stability(did) { - if stab.level.is_unstable() && stab.feature == sym::rustc_private { + if let StabilityLevel::Unstable { feature: sym::rustc_private, .. } = &stab.level { return; } } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 172fe5d164b7a..56d9d947261b8 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -640,11 +640,13 @@ fn short_item_info( // Render unstable items. But don't render "rustc_private" crates (internal compiler crates). // Those crates are permanently unstable so it makes no sense to render "unstable" everywhere. - if let Some((StabilityLevel::Unstable { reason, issue, .. }, feature)) = item + if let Some(StabilityLevel::Unstable { reason, feature, issue, .. }) = item .stability(cx.tcx()) .as_ref() - .filter(|stab| stab.feature != sym::rustc_private) - .map(|stab| (stab.level, stab.feature)) + .filter(|stab| { + !matches!(stab.level, StabilityLevel::Unstable { feature: sym::rustc_private, .. }) + }) + .map(|stab| stab.level) { let mut message = "🔬 This is a nightly-only experimental API.".to_owned(); @@ -801,7 +803,7 @@ fn render_stability_since_raw( match (ver, const_stability) { // stable and const stable - (Some(v), Some(ConstStability { level: StabilityLevel::Stable { since }, .. })) + (Some(v), Some(ConstStability { level: StabilityLevel::Stable { since, .. }, .. })) if Some(since.as_str()).as_deref() != containing_const_ver => { write!( @@ -813,7 +815,7 @@ fn render_stability_since_raw( // stable and const unstable ( Some(v), - Some(ConstStability { level: StabilityLevel::Unstable { issue, .. }, feature, .. }), + Some(ConstStability { level: StabilityLevel::Unstable { issue, feature, .. }, .. }), ) => { write!( w, diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 39ef641a3ace2..8f03793ec9c53 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -3,6 +3,7 @@ use clean::AttributesExt; use std::cmp::Ordering; use std::fmt; +use rustc_attr::StabilityLevel; use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; use rustc_hir::def::CtorKind; @@ -414,11 +415,10 @@ fn extra_info_tags(item: &clean::Item, parent: &clean::Item, tcx: TyCtxt<'_>) -> // The "rustc_private" crates are permanently unstable so it makes no sense // to render "unstable" everywhere. - if item - .stability(tcx) - .as_ref() - .map(|s| s.level.is_unstable() && s.feature != sym::rustc_private) - == Some(true) + if item.stability(tcx).as_ref().map(|s| { + matches!(s.level, StabilityLevel::Unstable { feature, .. } if feature != sym::rustc_private) + }) + == Some(true) { tags += &tag_html("unstable", "", "Experimental"); } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index b81acd1a93fc2..6f9d27a738bea 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -12,6 +12,7 @@ #![feature(crate_visibility_modifier)] #![feature(never_type)] #![feature(once_cell)] +#![feature(option_result_contains)] #![feature(type_ascription)] #![recursion_limit = "256"] #![warn(rustc::internal)] diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index e5bbf75c3b0a1..86c360b5b8388 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -368,7 +368,7 @@ fn check_terminator( fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: Option<&RustcVersion>) -> bool { rustc_mir::const_eval::is_const_fn(tcx, def_id) && tcx.lookup_const_stability(def_id).map_or(true, |const_stab| { - if let rustc_attr::StabilityLevel::Stable { since } = const_stab.level { + if let rustc_attr::StabilityLevel::Stable { since, .. } = const_stab.level { // Checking MSRV is manually necessary because `rustc` has no such concept. This entire // function could be removed if `rustc` provided a MSRV-aware version of `is_const_fn`. // as a part of an unimplemented MSRV check https://github.com/rust-lang/rust/issues/65262.