diff options
| author | Camille GILLOT <gillot.camille@gmail.com> | 2025-07-12 10:15:25 +0000 |
|---|---|---|
| committer | Camille GILLOT <gillot.camille@gmail.com> | 2025-07-17 22:48:41 +0000 |
| commit | 1eeb990e190298fb0b2197d52b7337def6f9215e (patch) | |
| tree | 536bfd7cbdc81782f9a60c2c2d6e9c0181ea6843 /compiler/rustc_passes/src/stability.rs | |
| parent | f6ef440816235b5737b5d5d6692328395611767c (diff) | |
| download | rust-1eeb990e190298fb0b2197d52b7337def6f9215e.tar.gz rust-1eeb990e190298fb0b2197d52b7337def6f9215e.zip | |
Querify lookup_stability.
Diffstat (limited to 'compiler/rustc_passes/src/stability.rs')
| -rw-r--r-- | compiler/rustc_passes/src/stability.rs | 225 |
1 files changed, 107 insertions, 118 deletions
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 5445b930540..3f6414fe962 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -150,6 +150,78 @@ fn lookup_deprecation_entry(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<Depre Some(DeprecationEntry::local(depr, def_id)) } +fn inherit_stability(def_kind: DefKind) -> InheritStability { + match def_kind { + DefKind::Field | DefKind::Variant | DefKind::Ctor(..) => InheritStability::Yes, + _ => InheritStability::No, + } +} + +/// If the `-Z force-unstable-if-unmarked` flag is passed then we provide +/// a parent stability annotation which indicates that this is private +/// with the `rustc_private` feature. This is intended for use when +/// compiling `librustc_*` crates themselves so we can leverage crates.io +/// while maintaining the invariant that all sysroot crates are unstable +/// by default and are unable to be used. +const FORCE_UNSTABLE: Stability = Stability { + level: attrs::StabilityLevel::Unstable { + reason: UnstableReason::Default, + issue: NonZero::new(27812), + is_soft: false, + implied_by: None, + old_name: None, + }, + feature: sym::rustc_private, +}; + +#[instrument(level = "debug", skip(tcx))] +fn lookup_stability(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<Stability> { + // Propagate unstability. This can happen even for non-staged-api crates in case + // -Zforce-unstable-if-unmarked is set. + if !tcx.features().staged_api() { + if !tcx.sess.opts.unstable_opts.force_unstable_if_unmarked { + return None; + } + + let Some(parent) = tcx.opt_local_parent(def_id) else { return Some(FORCE_UNSTABLE) }; + + if inherit_deprecation(tcx.def_kind(def_id)).yes() { + let parent = tcx.lookup_stability(parent)?; + if parent.is_unstable() { + return Some(parent); + } + } + + return None; + } + + // # Regular stability + let attrs = tcx.hir_attrs(tcx.local_def_id_to_hir_id(def_id)); + let stab = + attrs::find_attr!(attrs, AttributeKind::Stability { stability, span: _ } => *stability); + + if let Some(stab) = stab { + return Some(stab); + } + + if inherit_deprecation(tcx.def_kind(def_id)).yes() { + let Some(parent) = tcx.opt_local_parent(def_id) else { + return tcx + .sess + .opts + .unstable_opts + .force_unstable_if_unmarked + .then_some(FORCE_UNSTABLE); + }; + let parent = tcx.lookup_stability(parent)?; + if parent.is_unstable() || inherit_stability(tcx.def_kind(def_id)).yes() { + return Some(parent); + } + } + + None +} + #[instrument(level = "debug", skip(tcx))] fn lookup_default_body_stability( tcx: TyCtxt<'_>, @@ -168,7 +240,6 @@ fn lookup_default_body_stability( struct Annotator<'a, 'tcx> { tcx: TyCtxt<'tcx>, index: &'a mut Index, - parent_stab: Option<Stability>, parent_const_stab: Option<ConstStability>, } @@ -182,7 +253,6 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { fn_sig: Option<&'tcx hir::FnSig<'tcx>>, inherit_deprecation: InheritDeprecation, inherit_const_stability: InheritConstStability, - inherit_from_parent: InheritStability, visit_children: F, ) where F: FnOnce(&mut Self), @@ -190,14 +260,16 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { let attrs = self.tcx.hir_attrs(self.tcx.local_def_id_to_hir_id(def_id)); debug!("annotate(id = {:?}, attrs = {:?})", def_id, attrs); + let stab = self.tcx.lookup_stability(def_id); let const_stability_indirect = find_attr!(attrs, AttributeKind::ConstStabilityIndirect); if !self.tcx.features().staged_api() { // Propagate unstability. This can happen even for non-staged-api crates in case // -Zforce-unstable-if-unmarked is set. - if let Some(stab) = self.parent_stab { + if let Some(parent_def_id) = self.tcx.opt_local_parent(def_id) + && let Some(stab) = self.tcx.lookup_stability(parent_def_id) + { if inherit_deprecation.yes() && stab.is_unstable() { - self.index.stab_map.insert(def_id, stab); if fn_sig.is_some_and(|s| s.header.is_const()) { self.index.const_stab_map.insert( def_id, @@ -207,39 +279,18 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { } } - self.recurse_with_stability_attrs(None, None, visit_children); + self.recurse_with_stability_attrs(None, visit_children); return; } - // # Regular stability - let stab = - attrs::find_attr!(attrs, AttributeKind::Stability { stability, span: _ } => *stability); - - if let Some(stab) = stab { - debug!("annotate: found {:?}", stab); - - if let Stability { - level: StabilityLevel::Unstable { implied_by: Some(implied_by), .. }, - feature, - } = stab - { - self.index.implications.insert(implied_by, feature); - } - - self.index.stab_map.insert(def_id, stab); - } - - if stab.is_none() { - debug!("annotate: stab not found, parent = {:?}", self.parent_stab); - if let Some(stab) = self.parent_stab { - if inherit_deprecation.yes() && stab.is_unstable() || inherit_from_parent.yes() { - self.index.stab_map.insert(def_id, stab); - } - } + if let Some(Stability { + level: StabilityLevel::Unstable { implied_by: Some(implied_by), .. }, + feature, + }) = stab + { + self.index.implications.insert(implied_by, feature); } - let final_stab = self.index.stab_map.get(&def_id); - // # Const stability let const_stab = attrs::find_attr!(attrs, AttributeKind::ConstStability { stability, span: _ } => *stability); @@ -253,7 +304,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { if fn_sig.is_some_and(|s| s.header.is_const()) && const_stab.is_none() && // We only ever inherit unstable features. let Some(inherit_regular_stab) = - final_stab.filter(|s| s.is_unstable()) + stab.filter(|s| s.is_unstable()) { const_stab = Some(ConstStability { // We subject these implicitly-const functions to recursive const stability. @@ -292,7 +343,6 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { } self.recurse_with_stability_attrs( - stab, inherit_const_stability.yes().then_some(const_stab).flatten(), visit_children, ); @@ -300,17 +350,12 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { fn recurse_with_stability_attrs( &mut self, - stab: Option<Stability>, const_stab: Option<ConstStability>, f: impl FnOnce(&mut Self), ) { // These will be `Some` if this item changes the corresponding stability attribute. - let mut replaced_parent_stab = None; let mut replaced_parent_const_stab = None; - if let Some(stab) = stab { - replaced_parent_stab = Some(replace(&mut self.parent_stab, Some(stab))); - } if let Some(const_stab) = const_stab { replaced_parent_const_stab = Some(replace(&mut self.parent_const_stab, Some(const_stab))); @@ -318,9 +363,6 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { f(self); - if let Some(orig_parent_stab) = replaced_parent_stab { - self.parent_stab = orig_parent_stab; - } if let Some(orig_parent_const_stab) = replaced_parent_const_stab { self.parent_const_stab = orig_parent_const_stab; } @@ -352,7 +394,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { None, InheritDeprecation::Yes, InheritConstStability::No, - InheritStability::Yes, |_| {}, ) } @@ -368,7 +409,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { fn_sig, InheritDeprecation::Yes, const_stab_inherit, - InheritStability::No, |v| intravisit::walk_item(v, i), ); } @@ -384,7 +424,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { fn_sig, InheritDeprecation::Yes, InheritConstStability::No, - InheritStability::No, |v| { intravisit::walk_trait_item(v, ti); }, @@ -402,7 +441,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { fn_sig, InheritDeprecation::Yes, InheritConstStability::No, - InheritStability::No, |v| { intravisit::walk_impl_item(v, ii); }, @@ -410,40 +448,25 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { } fn visit_variant(&mut self, var: &'tcx Variant<'tcx>) { - self.annotate( - var.def_id, - None, - InheritDeprecation::Yes, - InheritConstStability::No, - InheritStability::Yes, - |v| { - if let Some(ctor_def_id) = var.data.ctor_def_id() { - v.annotate( - ctor_def_id, - None, - InheritDeprecation::Yes, - InheritConstStability::No, - InheritStability::Yes, - |_| {}, - ); - } + self.annotate(var.def_id, None, InheritDeprecation::Yes, InheritConstStability::No, |v| { + if let Some(ctor_def_id) = var.data.ctor_def_id() { + v.annotate( + ctor_def_id, + None, + InheritDeprecation::Yes, + InheritConstStability::No, + |_| {}, + ); + } - intravisit::walk_variant(v, var) - }, - ) + intravisit::walk_variant(v, var) + }) } fn visit_field_def(&mut self, s: &'tcx FieldDef<'tcx>) { - self.annotate( - s.def_id, - None, - InheritDeprecation::Yes, - InheritConstStability::No, - InheritStability::Yes, - |v| { - intravisit::walk_field_def(v, s); - }, - ); + self.annotate(s.def_id, None, InheritDeprecation::Yes, InheritConstStability::No, |v| { + intravisit::walk_field_def(v, s); + }); } fn visit_foreign_item(&mut self, i: &'tcx hir::ForeignItem<'tcx>) { @@ -456,7 +479,6 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { fn_sig, InheritDeprecation::Yes, InheritConstStability::No, - InheritStability::No, |v| { intravisit::walk_foreign_item(v, i); }, @@ -464,16 +486,9 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { } fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) { - self.annotate( - p.def_id, - None, - InheritDeprecation::No, - InheritConstStability::No, - InheritStability::No, - |v| { - intravisit::walk_generic_param(v, p); - }, - ); + self.annotate(p.def_id, None, InheritDeprecation::No, InheritConstStability::No, |v| { + intravisit::walk_generic_param(v, p); + }); } } @@ -580,7 +595,7 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> { } fn check_missing_stability(&self, def_id: LocalDefId, span: Span) { - let stab = self.tcx.stability().local_stability(def_id); + let stab = self.tcx.lookup_stability(def_id); if !self.tcx.sess.is_test_crate() && stab.is_none() && self.effective_visibilities.is_reachable(def_id) @@ -681,42 +696,16 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> { } fn stability_index(tcx: TyCtxt<'_>, (): ()) -> Index { - let mut index = Index { - stab_map: Default::default(), - const_stab_map: Default::default(), - implications: Default::default(), - }; + let mut index = Index { const_stab_map: Default::default(), implications: Default::default() }; { - let mut annotator = - Annotator { tcx, index: &mut index, parent_stab: None, parent_const_stab: None }; - - // If the `-Z force-unstable-if-unmarked` flag is passed then we provide - // a parent stability annotation which indicates that this is private - // with the `rustc_private` feature. This is intended for use when - // compiling `librustc_*` crates themselves so we can leverage crates.io - // while maintaining the invariant that all sysroot crates are unstable - // by default and are unable to be used. - if tcx.sess.opts.unstable_opts.force_unstable_if_unmarked { - let stability = Stability { - level: attrs::StabilityLevel::Unstable { - reason: UnstableReason::Default, - issue: NonZero::new(27812), - is_soft: false, - implied_by: None, - old_name: None, - }, - feature: sym::rustc_private, - }; - annotator.parent_stab = Some(stability); - } + let mut annotator = Annotator { tcx, index: &mut index, parent_const_stab: None }; annotator.annotate( CRATE_DEF_ID, None, InheritDeprecation::Yes, InheritConstStability::No, - InheritStability::No, |v| tcx.hir_walk_toplevel_module(v), ); } @@ -734,7 +723,7 @@ pub(crate) fn provide(providers: &mut Providers) { check_mod_unstable_api_usage, stability_index, stability_implications: |tcx, _| tcx.stability().implications.clone(), - lookup_stability: |tcx, id| tcx.stability().local_stability(id), + lookup_stability, lookup_const_stability: |tcx, id| tcx.stability().local_const_stability(id), lookup_default_body_stability, lookup_deprecation_entry, @@ -1042,7 +1031,7 @@ fn is_unstable_reexport(tcx: TyCtxt<'_>, id: hir::HirId) -> bool { }; let def_id = owner.def_id; - let Some(stab) = tcx.stability().local_stability(def_id) else { + let Some(stab) = tcx.lookup_stability(def_id) else { return false; }; |
