From 1523f67f16cb65da740d20b9853ce7f267579a7d Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Wed, 16 Dec 2020 15:54:05 -0500 Subject: [PATCH] Calculate stability, const_stability, and deprecation on-demand Previously, they would always be calculated ahead of time, which bloated the size of `clean::Item`. --- src/librustdoc/clean/auto_trait.rs | 3 - src/librustdoc/clean/blanket_impl.rs | 3 - src/librustdoc/clean/inline.rs | 3 - src/librustdoc/clean/mod.rs | 9 --- src/librustdoc/clean/types.rs | 34 ++++++----- src/librustdoc/html/render/mod.rs | 90 +++++++++++++++++----------- src/librustdoc/json/conversions.rs | 13 +--- 7 files changed, 75 insertions(+), 80 deletions(-) diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 40c59ed1e0b75..96d19e8e17de7 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -123,9 +123,6 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { attrs: Default::default(), visibility: Inherited, def_id: self.cx.next_def_id(param_env_def_id.krate), - stability: None, - const_stability: None, - deprecation: None, kind: ImplItem(Impl { unsafety: hir::Unsafety::Normal, generics: new_generics, diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index 33b5e84c5e074..0ecd71d008fc7 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -112,9 +112,6 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { attrs: Default::default(), visibility: Inherited, def_id: self.cx.next_def_id(impl_def_id.krate), - stability: None, - const_stability: None, - deprecation: None, kind: ImplItem(Impl { unsafety: hir::Unsafety::Normal, generics: ( diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 3cff5fa07b15c..fd30d62ea1fbe 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -482,9 +482,6 @@ fn build_module(cx: &DocContext<'_>, did: DefId, visited: &mut FxHashSet) source: clean::Span::dummy(), def_id: DefId::local(CRATE_DEF_INDEX), visibility: clean::Public, - stability: None, - const_stability: None, - deprecation: None, kind: clean::ImportItem(clean::Import::new_simple( item.ident.name, clean::ImportSource { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 2809e85761d41..0d3bfd26f9680 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2139,9 +2139,6 @@ fn clean_extern_crate( source: krate.span.clean(cx), def_id: crate_def_id, visibility: krate.vis.clean(cx), - stability: None, - const_stability: None, - deprecation: None, kind: ExternCrateItem(name, orig_name), }] } @@ -2210,9 +2207,6 @@ impl Clean> for doctree::Import<'_> { source: self.span.clean(cx), def_id: cx.tcx.hir().local_def_id(self.id).to_def_id(), visibility: self.vis.clean(cx), - stability: None, - const_stability: None, - deprecation: None, kind: ImportItem(Import::new_simple( self.name, resolve_use_source(cx, path), @@ -2231,9 +2225,6 @@ impl Clean> for doctree::Import<'_> { source: self.span.clean(cx), def_id: cx.tcx.hir().local_def_id(self.id).to_def_id(), visibility: self.vis.clean(cx), - stability: None, - const_stability: None, - deprecation: None, kind: ImportItem(inner), }] } diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 52d023c83cb67..9cff129993d28 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -86,9 +86,6 @@ crate struct Item { crate visibility: Visibility, crate kind: ItemKind, crate def_id: DefId, - crate stability: Option, - crate deprecation: Option, - crate const_stability: Option, } impl fmt::Debug for Item { @@ -102,13 +99,23 @@ impl fmt::Debug for Item { .field("kind", &self.kind) .field("visibility", &self.visibility) .field("def_id", def_id) - .field("stability", &self.stability) - .field("deprecation", &self.deprecation) .finish() } } impl Item { + crate fn stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx Stability> { + if self.is_fake() { None } else { tcx.lookup_stability(self.def_id) } + } + + crate fn const_stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ConstStability> { + if self.is_fake() { None } else { tcx.lookup_const_stability(self.def_id) } + } + + crate fn deprecation(&self, tcx: TyCtxt<'_>) -> Option { + if self.is_fake() { None } else { tcx.lookup_deprecation(self.def_id) } + } + /// Finds the `doc` attribute as a NameValue and returns the corresponding /// value found. crate fn doc_value(&self) -> Option<&str> { @@ -150,9 +157,6 @@ impl Item { source: source.clean(cx), attrs: cx.tcx.get_attrs(def_id).clean(cx), visibility: cx.tcx.visibility(def_id).clean(cx), - stability: cx.tcx.lookup_stability(def_id).cloned(), - deprecation: cx.tcx.lookup_deprecation(def_id), - const_stability: cx.tcx.lookup_const_stability(def_id).cloned(), } } @@ -236,8 +240,8 @@ impl Item { } } - crate fn stability_class(&self) -> Option { - self.stability.as_ref().and_then(|ref s| { + crate fn stability_class(&self, tcx: TyCtxt<'_>) -> Option { + self.stability(tcx).as_ref().and_then(|ref s| { let mut classes = Vec::with_capacity(2); if s.level.is_unstable() { @@ -245,7 +249,7 @@ impl Item { } // FIXME: what about non-staged API items that are deprecated? - if self.deprecation.is_some() { + if self.deprecation(tcx).is_some() { classes.push("deprecated"); } @@ -253,15 +257,15 @@ impl Item { }) } - crate fn stable_since(&self) -> Option { - match self.stability?.level { + crate fn stable_since(&self, tcx: TyCtxt<'_>) -> Option { + match self.stability(tcx)?.level { StabilityLevel::Stable { since, .. } => Some(since.as_str()), StabilityLevel::Unstable { .. } => None, } } - crate fn const_stable_since(&self) -> Option { - match self.const_stability?.level { + crate fn const_stable_since(&self, tcx: TyCtxt<'_>) -> Option { + match self.const_stability(tcx)?.level { StabilityLevel::Stable { since, .. } => Some(since.as_str()), StabilityLevel::Unstable { .. } => None, } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 67ccc3d4cf8d4..75c32481286b5 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -164,7 +164,7 @@ crate struct SharedContext<'tcx> { playground: Option, } -impl Context<'_> { +impl<'tcx> Context<'tcx> { fn path(&self, filename: &str) -> PathBuf { // We use splitn vs Path::extension here because we might get a filename // like `style.min.css` and we want to process that into @@ -176,6 +176,10 @@ impl Context<'_> { self.dst.join(&filename) } + fn tcx(&self) -> TyCtxt<'tcx> { + self.shared.tcx + } + fn sess(&self) -> &Session { &self.shared.tcx.sess } @@ -1708,8 +1712,8 @@ fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer, cache: &Ca write!(buf, "

"); render_stability_since_raw( buf, - item.stable_since().as_deref(), - item.const_stable_since().as_deref(), + item.stable_since(cx.tcx()).as_deref(), + item.const_stable_since(cx.tcx()).as_deref(), None, None, ); @@ -2061,14 +2065,20 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl } } - fn cmp(i1: &clean::Item, i2: &clean::Item, idx1: usize, idx2: usize) -> Ordering { + fn cmp( + i1: &clean::Item, + i2: &clean::Item, + idx1: usize, + idx2: usize, + tcx: TyCtxt<'_>, + ) -> Ordering { let ty1 = i1.type_(); let ty2 = i2.type_(); if ty1 != ty2 { return (reorder(ty1), idx1).cmp(&(reorder(ty2), idx2)); } - let s1 = i1.stability.as_ref().map(|s| s.level); - let s2 = i2.stability.as_ref().map(|s| s.level); + let s1 = i1.stability(tcx).as_ref().map(|s| s.level); + let s2 = i2.stability(tcx).as_ref().map(|s| s.level); if let (Some(a), Some(b)) = (s1, s2) { match (a.is_stable(), b.is_stable()) { (true, true) | (false, false) => {} @@ -2082,7 +2092,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl } if cx.shared.sort_modules_alphabetically { - indices.sort_by(|&i1, &i2| cmp(&items[i1], &items[i2], i1, i2)); + indices.sort_by(|&i1, &i2| cmp(&items[i1], &items[i2], i1, i2, cx.tcx())); } // This call is to remove re-export duplicates in cases such as: // @@ -2184,7 +2194,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl _ => "", }; - let stab = myitem.stability_class(); + let stab = myitem.stability_class(cx.tcx()); let add = if stab.is_some() { " " } else { "" }; let doc_value = myitem.doc_value().unwrap_or(""); @@ -2196,7 +2206,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl {stab_tags}{docs}\ ", name = *myitem.name.as_ref().unwrap(), - stab_tags = extra_info_tags(myitem, item), + stab_tags = extra_info_tags(myitem, item, cx.tcx()), docs = MarkdownSummaryLine(doc_value, &myitem.links()).into_string(), class = myitem.type_(), add = add, @@ -2220,7 +2230,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl /// Render the stability, deprecation and portability tags that are displayed in the item's summary /// at the module level. -fn extra_info_tags(item: &clean::Item, parent: &clean::Item) -> String { +fn extra_info_tags(item: &clean::Item, parent: &clean::Item, tcx: TyCtxt<'_>) -> String { let mut tags = String::new(); fn tag_html(class: &str, title: &str, contents: &str) -> String { @@ -2228,7 +2238,7 @@ fn extra_info_tags(item: &clean::Item, parent: &clean::Item) -> String { } // The trailing space after each tag is to space it properly against the rest of the docs. - if let Some(depr) = &item.deprecation { + if let Some(depr) = &item.deprecation(tcx) { let mut message = "Deprecated"; if !stability::deprecation_in_effect( depr.is_since_rustc_version, @@ -2241,7 +2251,10 @@ fn extra_info_tags(item: &clean::Item, parent: &clean::Item) -> String { // The "rustc_private" crates are permanently unstable so it makes no sense // to render "unstable" everywhere. - if item.stability.as_ref().map(|s| s.level.is_unstable() && s.feature != sym::rustc_private) + if item + .stability(tcx) + .as_ref() + .map(|s| s.level.is_unstable() && s.feature != sym::rustc_private) == Some(true) { tags += &tag_html("unstable", "", "Experimental"); @@ -2287,7 +2300,7 @@ fn short_item_info( let error_codes = cx.shared.codes; if let Some(Deprecation { note, since, is_since_rustc_version, suggestion: _ }) = - item.deprecation + item.deprecation(cx.tcx()) { // We display deprecation messages for #[deprecated] and #[rustc_deprecated] // but only display the future-deprecation messages for #[rustc_deprecated]. @@ -2327,7 +2340,7 @@ 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 - .stability + .stability(cx.tcx()) .as_ref() .filter(|stab| stab.feature != sym::rustc_private) .map(|stab| (stab.level, stab.feature)) @@ -2480,8 +2493,8 @@ fn render_implementor( parent, AssocItemLink::Anchor(None), RenderMode::Normal, - implementor.impl_item.stable_since().as_deref(), - implementor.impl_item.const_stable_since().as_deref(), + implementor.impl_item.stable_since(cx.tcx()).as_deref(), + implementor.impl_item.const_stable_since(cx.tcx()).as_deref(), false, Some(use_absolute), false, @@ -2511,8 +2524,8 @@ fn render_impls( containing_item, assoc_link, RenderMode::Normal, - containing_item.stable_since().as_deref(), - containing_item.const_stable_since().as_deref(), + containing_item.stable_since(cx.tcx()).as_deref(), + containing_item.const_stable_since(cx.tcx()).as_deref(), true, None, false, @@ -2661,7 +2674,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra write!(w, "

", id = id,); render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl); write!(w, ""); - render_stability_since(w, m, t); + render_stability_since(w, m, t, cx.tcx()); write_srclink(cx, m, w, cache); write!(w, "

"); document(w, cx, m, Some(t)); @@ -2768,8 +2781,8 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra it, assoc_link, RenderMode::Normal, - implementor.impl_item.stable_since().as_deref(), - implementor.impl_item.const_stable_since().as_deref(), + implementor.impl_item.stable_since(cx.tcx()).as_deref(), + implementor.impl_item.const_stable_since(cx.tcx()).as_deref(), false, None, true, @@ -2950,13 +2963,18 @@ fn render_stability_since_raw( } } -fn render_stability_since(w: &mut Buffer, item: &clean::Item, containing_item: &clean::Item) { +fn render_stability_since( + w: &mut Buffer, + item: &clean::Item, + containing_item: &clean::Item, + tcx: TyCtxt<'_>, +) { render_stability_since_raw( w, - item.stable_since().as_deref(), - item.const_stable_since().as_deref(), - containing_item.stable_since().as_deref(), - containing_item.const_stable_since().as_deref(), + item.stable_since(tcx).as_deref(), + item.const_stable_since(tcx).as_deref(), + containing_item.stable_since(tcx).as_deref(), + containing_item.const_stable_since(tcx).as_deref(), ) } @@ -3149,7 +3167,7 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni shortty = ItemType::StructField, ty = ty.print() ); - if let Some(stability_class) = field.stability_class() { + if let Some(stability_class) = field.stability_class(cx.tcx()) { write!(w, "", stab = stability_class); } document(w, cx, field, Some(it)); @@ -3279,7 +3297,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum } write!(w, ""); } - render_stability_since(w, variant, it); + render_stability_since(w, variant, it, cx.tcx()); } } render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache) @@ -3510,8 +3528,8 @@ fn render_assoc_items( containing_item, AssocItemLink::Anchor(None), render_mode, - containing_item.stable_since().as_deref(), - containing_item.const_stable_since().as_deref(), + containing_item.stable_since(cx.tcx()).as_deref(), + containing_item.const_stable_since(cx.tcx()).as_deref(), true, None, false, @@ -3758,8 +3776,8 @@ fn render_impl( write!(w, "", id); render_stability_since_raw( w, - i.impl_item.stable_since().as_deref(), - i.impl_item.const_stable_since().as_deref(), + i.impl_item.stable_since(cx.tcx()).as_deref(), + i.impl_item.const_stable_since(cx.tcx()).as_deref(), outer_version, outer_const_version, ); @@ -3831,8 +3849,8 @@ fn render_impl( write!(w, ""); render_stability_since_raw( w, - item.stable_since().as_deref(), - item.const_stable_since().as_deref(), + item.stable_since(cx.tcx()).as_deref(), + item.const_stable_since(cx.tcx()).as_deref(), outer_version, outer_const_version, ); @@ -3853,8 +3871,8 @@ fn render_impl( write!(w, ""); render_stability_since_raw( w, - item.stable_since().as_deref(), - item.const_stable_since().as_deref(), + item.stable_since(cx.tcx()).as_deref(), + item.const_stable_since(cx.tcx()).as_deref(), outer_version, outer_const_version, ); diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 99587f4ec64e9..ef490086ed043 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -17,17 +17,8 @@ use crate::json::JsonRenderer; impl JsonRenderer<'_> { pub(super) fn convert_item(&self, item: clean::Item) -> Option { let item_type = ItemType::from(&item); - let clean::Item { - source, - name, - attrs, - kind, - visibility, - def_id, - stability: _, - const_stability: _, - deprecation, - } = item; + let deprecation = item.deprecation(self.tcx); + let clean::Item { source, name, attrs, kind, visibility, def_id } = item; match kind { clean::StrippedItem(_) => None, _ => Some(Item {