1
Fork 0

Calculate stability, const_stability, and deprecation on-demand

Previously, they would always be calculated ahead of time, which bloated
the size of `clean::Item`.
This commit is contained in:
Joshua Nelson 2020-12-16 15:54:05 -05:00
parent d8d3ab96aa
commit 1523f67f16
7 changed files with 75 additions and 80 deletions

View file

@ -123,9 +123,6 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
attrs: Default::default(), attrs: Default::default(),
visibility: Inherited, visibility: Inherited,
def_id: self.cx.next_def_id(param_env_def_id.krate), def_id: self.cx.next_def_id(param_env_def_id.krate),
stability: None,
const_stability: None,
deprecation: None,
kind: ImplItem(Impl { kind: ImplItem(Impl {
unsafety: hir::Unsafety::Normal, unsafety: hir::Unsafety::Normal,
generics: new_generics, generics: new_generics,

View file

@ -112,9 +112,6 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
attrs: Default::default(), attrs: Default::default(),
visibility: Inherited, visibility: Inherited,
def_id: self.cx.next_def_id(impl_def_id.krate), def_id: self.cx.next_def_id(impl_def_id.krate),
stability: None,
const_stability: None,
deprecation: None,
kind: ImplItem(Impl { kind: ImplItem(Impl {
unsafety: hir::Unsafety::Normal, unsafety: hir::Unsafety::Normal,
generics: ( generics: (

View file

@ -482,9 +482,6 @@ fn build_module(cx: &DocContext<'_>, did: DefId, visited: &mut FxHashSet<DefId>)
source: clean::Span::dummy(), source: clean::Span::dummy(),
def_id: DefId::local(CRATE_DEF_INDEX), def_id: DefId::local(CRATE_DEF_INDEX),
visibility: clean::Public, visibility: clean::Public,
stability: None,
const_stability: None,
deprecation: None,
kind: clean::ImportItem(clean::Import::new_simple( kind: clean::ImportItem(clean::Import::new_simple(
item.ident.name, item.ident.name,
clean::ImportSource { clean::ImportSource {

View file

@ -2139,9 +2139,6 @@ fn clean_extern_crate(
source: krate.span.clean(cx), source: krate.span.clean(cx),
def_id: crate_def_id, def_id: crate_def_id,
visibility: krate.vis.clean(cx), visibility: krate.vis.clean(cx),
stability: None,
const_stability: None,
deprecation: None,
kind: ExternCrateItem(name, orig_name), kind: ExternCrateItem(name, orig_name),
}] }]
} }
@ -2210,9 +2207,6 @@ impl Clean<Vec<Item>> for doctree::Import<'_> {
source: self.span.clean(cx), source: self.span.clean(cx),
def_id: cx.tcx.hir().local_def_id(self.id).to_def_id(), def_id: cx.tcx.hir().local_def_id(self.id).to_def_id(),
visibility: self.vis.clean(cx), visibility: self.vis.clean(cx),
stability: None,
const_stability: None,
deprecation: None,
kind: ImportItem(Import::new_simple( kind: ImportItem(Import::new_simple(
self.name, self.name,
resolve_use_source(cx, path), resolve_use_source(cx, path),
@ -2231,9 +2225,6 @@ impl Clean<Vec<Item>> for doctree::Import<'_> {
source: self.span.clean(cx), source: self.span.clean(cx),
def_id: cx.tcx.hir().local_def_id(self.id).to_def_id(), def_id: cx.tcx.hir().local_def_id(self.id).to_def_id(),
visibility: self.vis.clean(cx), visibility: self.vis.clean(cx),
stability: None,
const_stability: None,
deprecation: None,
kind: ImportItem(inner), kind: ImportItem(inner),
}] }]
} }

View file

@ -86,9 +86,6 @@ crate struct Item {
crate visibility: Visibility, crate visibility: Visibility,
crate kind: ItemKind, crate kind: ItemKind,
crate def_id: DefId, crate def_id: DefId,
crate stability: Option<Stability>,
crate deprecation: Option<Deprecation>,
crate const_stability: Option<ConstStability>,
} }
impl fmt::Debug for Item { impl fmt::Debug for Item {
@ -102,13 +99,23 @@ impl fmt::Debug for Item {
.field("kind", &self.kind) .field("kind", &self.kind)
.field("visibility", &self.visibility) .field("visibility", &self.visibility)
.field("def_id", def_id) .field("def_id", def_id)
.field("stability", &self.stability)
.field("deprecation", &self.deprecation)
.finish() .finish()
} }
} }
impl Item { 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<Deprecation> {
if self.is_fake() { None } else { tcx.lookup_deprecation(self.def_id) }
}
/// Finds the `doc` attribute as a NameValue and returns the corresponding /// Finds the `doc` attribute as a NameValue and returns the corresponding
/// value found. /// value found.
crate fn doc_value(&self) -> Option<&str> { crate fn doc_value(&self) -> Option<&str> {
@ -150,9 +157,6 @@ impl Item {
source: source.clean(cx), source: source.clean(cx),
attrs: cx.tcx.get_attrs(def_id).clean(cx), attrs: cx.tcx.get_attrs(def_id).clean(cx),
visibility: cx.tcx.visibility(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<String> { crate fn stability_class(&self, tcx: TyCtxt<'_>) -> Option<String> {
self.stability.as_ref().and_then(|ref s| { self.stability(tcx).as_ref().and_then(|ref s| {
let mut classes = Vec::with_capacity(2); let mut classes = Vec::with_capacity(2);
if s.level.is_unstable() { if s.level.is_unstable() {
@ -245,7 +249,7 @@ impl Item {
} }
// FIXME: what about non-staged API items that are deprecated? // FIXME: what about non-staged API items that are deprecated?
if self.deprecation.is_some() { if self.deprecation(tcx).is_some() {
classes.push("deprecated"); classes.push("deprecated");
} }
@ -253,15 +257,15 @@ impl Item {
}) })
} }
crate fn stable_since(&self) -> Option<SymbolStr> { crate fn stable_since(&self, tcx: TyCtxt<'_>) -> Option<SymbolStr> {
match self.stability?.level { match self.stability(tcx)?.level {
StabilityLevel::Stable { since, .. } => Some(since.as_str()), StabilityLevel::Stable { since, .. } => Some(since.as_str()),
StabilityLevel::Unstable { .. } => None, StabilityLevel::Unstable { .. } => None,
} }
} }
crate fn const_stable_since(&self) -> Option<SymbolStr> { crate fn const_stable_since(&self, tcx: TyCtxt<'_>) -> Option<SymbolStr> {
match self.const_stability?.level { match self.const_stability(tcx)?.level {
StabilityLevel::Stable { since, .. } => Some(since.as_str()), StabilityLevel::Stable { since, .. } => Some(since.as_str()),
StabilityLevel::Unstable { .. } => None, StabilityLevel::Unstable { .. } => None,
} }

View file

@ -164,7 +164,7 @@ crate struct SharedContext<'tcx> {
playground: Option<markdown::Playground>, playground: Option<markdown::Playground>,
} }
impl Context<'_> { impl<'tcx> Context<'tcx> {
fn path(&self, filename: &str) -> PathBuf { fn path(&self, filename: &str) -> PathBuf {
// We use splitn vs Path::extension here because we might get a filename // We use splitn vs Path::extension here because we might get a filename
// like `style.min.css` and we want to process that into // like `style.min.css` and we want to process that into
@ -176,6 +176,10 @@ impl Context<'_> {
self.dst.join(&filename) self.dst.join(&filename)
} }
fn tcx(&self) -> TyCtxt<'tcx> {
self.shared.tcx
}
fn sess(&self) -> &Session { fn sess(&self) -> &Session {
&self.shared.tcx.sess &self.shared.tcx.sess
} }
@ -1708,8 +1712,8 @@ fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer, cache: &Ca
write!(buf, "<h1 class=\"fqn\"><span class=\"out-of-band\">"); write!(buf, "<h1 class=\"fqn\"><span class=\"out-of-band\">");
render_stability_since_raw( render_stability_since_raw(
buf, buf,
item.stable_since().as_deref(), item.stable_since(cx.tcx()).as_deref(),
item.const_stable_since().as_deref(), item.const_stable_since(cx.tcx()).as_deref(),
None, None,
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 ty1 = i1.type_();
let ty2 = i2.type_(); let ty2 = i2.type_();
if ty1 != ty2 { if ty1 != ty2 {
return (reorder(ty1), idx1).cmp(&(reorder(ty2), idx2)); return (reorder(ty1), idx1).cmp(&(reorder(ty2), idx2));
} }
let s1 = i1.stability.as_ref().map(|s| s.level); let s1 = i1.stability(tcx).as_ref().map(|s| s.level);
let s2 = i2.stability.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) { if let (Some(a), Some(b)) = (s1, s2) {
match (a.is_stable(), b.is_stable()) { match (a.is_stable(), b.is_stable()) {
(true, true) | (false, false) => {} (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 { 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: // 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 add = if stab.is_some() { " " } else { "" };
let doc_value = myitem.doc_value().unwrap_or(""); 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
<td class=\"docblock-short\">{stab_tags}{docs}</td>\ <td class=\"docblock-short\">{stab_tags}{docs}</td>\
</tr>", </tr>",
name = *myitem.name.as_ref().unwrap(), 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(), docs = MarkdownSummaryLine(doc_value, &myitem.links()).into_string(),
class = myitem.type_(), class = myitem.type_(),
add = add, 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 /// Render the stability, deprecation and portability tags that are displayed in the item's summary
/// at the module level. /// 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(); let mut tags = String::new();
fn tag_html(class: &str, title: &str, contents: &str) -> String { 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. // 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"; let mut message = "Deprecated";
if !stability::deprecation_in_effect( if !stability::deprecation_in_effect(
depr.is_since_rustc_version, 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 // The "rustc_private" crates are permanently unstable so it makes no sense
// to render "unstable" everywhere. // 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) == Some(true)
{ {
tags += &tag_html("unstable", "", "Experimental"); tags += &tag_html("unstable", "", "Experimental");
@ -2287,7 +2300,7 @@ fn short_item_info(
let error_codes = cx.shared.codes; let error_codes = cx.shared.codes;
if let Some(Deprecation { note, since, is_since_rustc_version, suggestion: _ }) = 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] // We display deprecation messages for #[deprecated] and #[rustc_deprecated]
// but only display the future-deprecation messages for #[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). // 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. // 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, issue, .. }, feature)) = item
.stability .stability(cx.tcx())
.as_ref() .as_ref()
.filter(|stab| stab.feature != sym::rustc_private) .filter(|stab| stab.feature != sym::rustc_private)
.map(|stab| (stab.level, stab.feature)) .map(|stab| (stab.level, stab.feature))
@ -2480,8 +2493,8 @@ fn render_implementor(
parent, parent,
AssocItemLink::Anchor(None), AssocItemLink::Anchor(None),
RenderMode::Normal, RenderMode::Normal,
implementor.impl_item.stable_since().as_deref(), implementor.impl_item.stable_since(cx.tcx()).as_deref(),
implementor.impl_item.const_stable_since().as_deref(), implementor.impl_item.const_stable_since(cx.tcx()).as_deref(),
false, false,
Some(use_absolute), Some(use_absolute),
false, false,
@ -2511,8 +2524,8 @@ fn render_impls(
containing_item, containing_item,
assoc_link, assoc_link,
RenderMode::Normal, RenderMode::Normal,
containing_item.stable_since().as_deref(), containing_item.stable_since(cx.tcx()).as_deref(),
containing_item.const_stable_since().as_deref(), containing_item.const_stable_since(cx.tcx()).as_deref(),
true, true,
None, None,
false, false,
@ -2661,7 +2674,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
write!(w, "<h3 id=\"{id}\" class=\"method\"><code>", id = id,); write!(w, "<h3 id=\"{id}\" class=\"method\"><code>", id = id,);
render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl); render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl);
write!(w, "</code>"); write!(w, "</code>");
render_stability_since(w, m, t); render_stability_since(w, m, t, cx.tcx());
write_srclink(cx, m, w, cache); write_srclink(cx, m, w, cache);
write!(w, "</h3>"); write!(w, "</h3>");
document(w, cx, m, Some(t)); 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, it,
assoc_link, assoc_link,
RenderMode::Normal, RenderMode::Normal,
implementor.impl_item.stable_since().as_deref(), implementor.impl_item.stable_since(cx.tcx()).as_deref(),
implementor.impl_item.const_stable_since().as_deref(), implementor.impl_item.const_stable_since(cx.tcx()).as_deref(),
false, false,
None, None,
true, 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( render_stability_since_raw(
w, w,
item.stable_since().as_deref(), item.stable_since(tcx).as_deref(),
item.const_stable_since().as_deref(), item.const_stable_since(tcx).as_deref(),
containing_item.stable_since().as_deref(), containing_item.stable_since(tcx).as_deref(),
containing_item.const_stable_since().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, shortty = ItemType::StructField,
ty = ty.print() ty = ty.print()
); );
if let Some(stability_class) = field.stability_class() { if let Some(stability_class) = field.stability_class(cx.tcx()) {
write!(w, "<span class=\"stab {stab}\"></span>", stab = stability_class); write!(w, "<span class=\"stab {stab}\"></span>", stab = stability_class);
} }
document(w, cx, field, Some(it)); 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, "</div></div>"); write!(w, "</div></div>");
} }
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) render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache)
@ -3510,8 +3528,8 @@ fn render_assoc_items(
containing_item, containing_item,
AssocItemLink::Anchor(None), AssocItemLink::Anchor(None),
render_mode, render_mode,
containing_item.stable_since().as_deref(), containing_item.stable_since(cx.tcx()).as_deref(),
containing_item.const_stable_since().as_deref(), containing_item.const_stable_since(cx.tcx()).as_deref(),
true, true,
None, None,
false, false,
@ -3758,8 +3776,8 @@ fn render_impl(
write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id); write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id);
render_stability_since_raw( render_stability_since_raw(
w, w,
i.impl_item.stable_since().as_deref(), i.impl_item.stable_since(cx.tcx()).as_deref(),
i.impl_item.const_stable_since().as_deref(), i.impl_item.const_stable_since(cx.tcx()).as_deref(),
outer_version, outer_version,
outer_const_version, outer_const_version,
); );
@ -3831,8 +3849,8 @@ fn render_impl(
write!(w, "</code>"); write!(w, "</code>");
render_stability_since_raw( render_stability_since_raw(
w, w,
item.stable_since().as_deref(), item.stable_since(cx.tcx()).as_deref(),
item.const_stable_since().as_deref(), item.const_stable_since(cx.tcx()).as_deref(),
outer_version, outer_version,
outer_const_version, outer_const_version,
); );
@ -3853,8 +3871,8 @@ fn render_impl(
write!(w, "</code>"); write!(w, "</code>");
render_stability_since_raw( render_stability_since_raw(
w, w,
item.stable_since().as_deref(), item.stable_since(cx.tcx()).as_deref(),
item.const_stable_since().as_deref(), item.const_stable_since(cx.tcx()).as_deref(),
outer_version, outer_version,
outer_const_version, outer_const_version,
); );

View file

@ -17,17 +17,8 @@ use crate::json::JsonRenderer;
impl JsonRenderer<'_> { impl JsonRenderer<'_> {
pub(super) fn convert_item(&self, item: clean::Item) -> Option<Item> { pub(super) fn convert_item(&self, item: clean::Item) -> Option<Item> {
let item_type = ItemType::from(&item); let item_type = ItemType::from(&item);
let clean::Item { let deprecation = item.deprecation(self.tcx);
source, let clean::Item { source, name, attrs, kind, visibility, def_id } = item;
name,
attrs,
kind,
visibility,
def_id,
stability: _,
const_stability: _,
deprecation,
} = item;
match kind { match kind {
clean::StrippedItem(_) => None, clean::StrippedItem(_) => None,
_ => Some(Item { _ => Some(Item {