1
Fork 0

Pass Context as a &mut to allow to remove RefCell fields

This commit is contained in:
Guillaume Gomez 2022-05-26 20:18:00 +02:00
parent 1ab98933fa
commit 6ab8edb931
5 changed files with 128 additions and 111 deletions

View file

@ -55,9 +55,9 @@ pub(crate) struct Context<'tcx> {
pub(super) render_redirect_pages: bool, pub(super) render_redirect_pages: bool,
/// Tracks section IDs for `Deref` targets so they match in both the main /// Tracks section IDs for `Deref` targets so they match in both the main
/// body and the sidebar. /// body and the sidebar.
pub(super) deref_id_map: RefCell<FxHashMap<DefId, String>>, pub(super) deref_id_map: FxHashMap<DefId, String>,
/// The map used to ensure all generated 'id=' attributes are unique. /// The map used to ensure all generated 'id=' attributes are unique.
pub(super) id_map: RefCell<IdMap>, pub(super) id_map: IdMap,
/// Shared mutable state. /// Shared mutable state.
/// ///
/// Issue for improving the situation: [#82381][] /// Issue for improving the situation: [#82381][]
@ -72,7 +72,7 @@ pub(crate) struct Context<'tcx> {
// `Context` is cloned a lot, so we don't want the size to grow unexpectedly. // `Context` is cloned a lot, so we don't want the size to grow unexpectedly.
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
rustc_data_structures::static_assert_size!(Context<'_>, 144); rustc_data_structures::static_assert_size!(Context<'_>, 128);
/// Shared mutable state used in [`Context`] and elsewhere. /// Shared mutable state used in [`Context`] and elsewhere.
pub(crate) struct SharedContext<'tcx> { pub(crate) struct SharedContext<'tcx> {
@ -155,9 +155,8 @@ impl<'tcx> Context<'tcx> {
self.shared.tcx.sess self.shared.tcx.sess
} }
pub(super) fn derive_id(&self, id: String) -> String { pub(super) fn derive_id(&mut self, id: String) -> String {
let mut map = self.id_map.borrow_mut(); self.id_map.derive(id)
map.derive(id)
} }
/// String representation of how to get back to the root path of the 'doc/' /// String representation of how to get back to the root path of the 'doc/'
@ -166,7 +165,7 @@ impl<'tcx> Context<'tcx> {
"../".repeat(self.current.len()) "../".repeat(self.current.len())
} }
fn render_item(&self, it: &clean::Item, is_module: bool) -> String { fn render_item(&mut self, it: &clean::Item, is_module: bool) -> String {
let mut title = String::new(); let mut title = String::new();
if !is_module { if !is_module {
title.push_str(it.name.unwrap().as_str()); title.push_str(it.name.unwrap().as_str());
@ -203,23 +202,26 @@ impl<'tcx> Context<'tcx> {
}; };
if !self.render_redirect_pages { if !self.render_redirect_pages {
let clone_shared = Rc::clone(&self.shared);
let page = layout::Page { let page = layout::Page {
css_class: tyname_s, css_class: tyname_s,
root_path: &self.root_path(), root_path: &self.root_path(),
static_root_path: self.shared.static_root_path.as_deref(), static_root_path: clone_shared.static_root_path.as_deref(),
title: &title, title: &title,
description: &desc, description: &desc,
keywords: &keywords, keywords: &keywords,
resource_suffix: &self.shared.resource_suffix, resource_suffix: &clone_shared.resource_suffix,
extra_scripts: &[], extra_scripts: &[],
static_extra_scripts: &[], static_extra_scripts: &[],
}; };
let mut page_buffer = Buffer::html();
print_item(self, it, &mut page_buffer, &page);
layout::render( layout::render(
&self.shared.layout, &clone_shared.layout,
&page, &page,
|buf: &mut _| print_sidebar(self, it, buf), |buf: &mut _| print_sidebar(self, it, buf),
|buf: &mut _| print_item(self, it, buf, &page), move |buf: &mut Buffer| buf.push_buffer(page_buffer),
&self.shared.style_files, &clone_shared.style_files,
) )
} else { } else {
if let Some(&(ref names, ty)) = self.cache().paths.get(&it.item_id.expect_def_id()) { if let Some(&(ref names, ty)) = self.cache().paths.get(&it.item_id.expect_def_id()) {
@ -512,8 +514,8 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
current: Vec::new(), current: Vec::new(),
dst, dst,
render_redirect_pages: false, render_redirect_pages: false,
id_map: RefCell::new(id_map), id_map,
deref_id_map: RefCell::new(FxHashMap::default()), deref_id_map: FxHashMap::default(),
shared: Rc::new(scx), shared: Rc::new(scx),
include_sources, include_sources,
}; };
@ -528,7 +530,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
// Write shared runs within a flock; disable thread dispatching of IO temporarily. // Write shared runs within a flock; disable thread dispatching of IO temporarily.
Rc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(true); Rc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(true);
write_shared(&cx, &krate, index, &md_opts)?; write_shared(&mut cx, &krate, index, &md_opts)?;
Rc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(false); Rc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(false);
} }
@ -540,8 +542,8 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
current: self.current.clone(), current: self.current.clone(),
dst: self.dst.clone(), dst: self.dst.clone(),
render_redirect_pages: self.render_redirect_pages, render_redirect_pages: self.render_redirect_pages,
deref_id_map: RefCell::new(FxHashMap::default()), deref_id_map: FxHashMap::default(),
id_map: RefCell::new(IdMap::new()), id_map: IdMap::new(),
shared: Rc::clone(&self.shared), shared: Rc::clone(&self.shared),
include_sources: self.include_sources, include_sources: self.include_sources,
} }
@ -557,31 +559,32 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
if !root_path.ends_with('/') { if !root_path.ends_with('/') {
root_path.push('/'); root_path.push('/');
} }
let shared = Rc::clone(&self.shared);
let mut page = layout::Page { let mut page = layout::Page {
title: "List of all items in this crate", title: "List of all items in this crate",
css_class: "mod", css_class: "mod",
root_path: "../", root_path: "../",
static_root_path: self.shared.static_root_path.as_deref(), static_root_path: shared.static_root_path.as_deref(),
description: "List of all items in this crate", description: "List of all items in this crate",
keywords: BASIC_KEYWORDS, keywords: BASIC_KEYWORDS,
resource_suffix: &self.shared.resource_suffix, resource_suffix: &shared.resource_suffix,
extra_scripts: &[], extra_scripts: &[],
static_extra_scripts: &[], static_extra_scripts: &[],
}; };
let sidebar = if self.shared.cache.crate_version.is_some() { let sidebar = if shared.cache.crate_version.is_some() {
format!("<h2 class=\"location\">Crate {}</h2>", crate_name) format!("<h2 class=\"location\">Crate {}</h2>", crate_name)
} else { } else {
String::new() String::new()
}; };
let all = self.shared.all.replace(AllTypes::new()); let all = shared.all.replace(AllTypes::new());
let v = layout::render( let v = layout::render(
&self.shared.layout, &shared.layout,
&page, &page,
sidebar, sidebar,
|buf: &mut Buffer| all.print(buf), |buf: &mut Buffer| all.print(buf),
&self.shared.style_files, &shared.style_files,
); );
self.shared.fs.write(final_file, v)?; shared.fs.write(final_file, v)?;
// Generating settings page. // Generating settings page.
page.title = "Rustdoc settings"; page.title = "Rustdoc settings";
@ -590,7 +593,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
let sidebar = "<h2 class=\"location\">Settings</h2><div class=\"sidebar-elems\"></div>"; let sidebar = "<h2 class=\"location\">Settings</h2><div class=\"sidebar-elems\"></div>";
let v = layout::render( let v = layout::render(
&self.shared.layout, &shared.layout,
&page, &page,
sidebar, sidebar,
|buf: &mut Buffer| { |buf: &mut Buffer| {
@ -613,33 +616,36 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
suffix = page.resource_suffix, suffix = page.resource_suffix,
) )
}, },
&self.shared.style_files, &shared.style_files,
); );
self.shared.fs.write(settings_file, v)?; shared.fs.write(settings_file, v)?;
if self.shared.layout.scrape_examples_extension { if shared.layout.scrape_examples_extension {
page.title = "About scraped examples"; page.title = "About scraped examples";
page.description = "How the scraped examples feature works in Rustdoc"; page.description = "How the scraped examples feature works in Rustdoc";
let v = layout::render( let v = layout::render(
&self.shared.layout, &shared.layout,
&page, &page,
"", "",
scrape_examples_help(&*self.shared), scrape_examples_help(&*shared),
&self.shared.style_files, &shared.style_files,
); );
self.shared.fs.write(scrape_examples_help_file, v)?; shared.fs.write(scrape_examples_help_file, v)?;
} }
if let Some(ref redirections) = self.shared.redirections { if let Some(ref redirections) = shared.redirections {
if !redirections.borrow().is_empty() { if !redirections.borrow().is_empty() {
let redirect_map_path = let redirect_map_path =
self.dst.join(crate_name.as_str()).join("redirect-map.json"); self.dst.join(crate_name.as_str()).join("redirect-map.json");
let paths = serde_json::to_string(&*redirections.borrow()).unwrap(); let paths = serde_json::to_string(&*redirections.borrow()).unwrap();
self.shared.ensure_dir(&self.dst.join(crate_name.as_str()))?; shared.ensure_dir(&self.dst.join(crate_name.as_str()))?;
self.shared.fs.write(redirect_map_path, paths)?; shared.fs.write(redirect_map_path, paths)?;
} }
} }
// No need for it anymore.
drop(shared);
// Flush pending errors. // Flush pending errors.
Rc::get_mut(&mut self.shared).unwrap().fs.close(); Rc::get_mut(&mut self.shared).unwrap().fs.close();
let nb_errors = let nb_errors =
@ -662,7 +668,6 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
if !self.render_redirect_pages { if !self.render_redirect_pages {
self.render_redirect_pages = item.is_stripped(); self.render_redirect_pages = item.is_stripped();
} }
let scx = &self.shared;
let item_name = item.name.unwrap(); let item_name = item.name.unwrap();
self.dst.push(&*item_name.as_str()); self.dst.push(&*item_name.as_str());
self.current.push(item_name); self.current.push(item_name);
@ -674,7 +679,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
if !buf.is_empty() { if !buf.is_empty() {
self.shared.ensure_dir(&self.dst)?; self.shared.ensure_dir(&self.dst)?;
let joint_dst = self.dst.join("index.html"); let joint_dst = self.dst.join("index.html");
scx.fs.write(joint_dst, buf)?; self.shared.fs.write(joint_dst, buf)?;
} }
// Render sidebar-items.js used throughout this module. // Render sidebar-items.js used throughout this module.
@ -684,7 +689,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
let items = self.build_sidebar_items(module); let items = self.build_sidebar_items(module);
let js_dst = self.dst.join(&format!("sidebar-items{}.js", self.shared.resource_suffix)); let js_dst = self.dst.join(&format!("sidebar-items{}.js", self.shared.resource_suffix));
let v = format!("initSidebarItems({});", serde_json::to_string(&items).unwrap()); let v = format!("initSidebarItems({});", serde_json::to_string(&items).unwrap());
scx.fs.write(js_dst, v)?; self.shared.fs.write(js_dst, v)?;
} }
Ok(()) Ok(())
} }

View file

@ -42,6 +42,7 @@ use std::fmt;
use std::fs; use std::fs;
use std::iter::Peekable; use std::iter::Peekable;
use std::path::PathBuf; use std::path::PathBuf;
use std::rc::Rc;
use std::str; use std::str;
use std::string::ToString; use std::string::ToString;
@ -364,7 +365,7 @@ fn scrape_examples_help(shared: &SharedContext<'_>) -> String {
fn document( fn document(
w: &mut Buffer, w: &mut Buffer,
cx: &Context<'_>, cx: &mut Context<'_>,
item: &clean::Item, item: &clean::Item,
parent: Option<&clean::Item>, parent: Option<&clean::Item>,
heading_offset: HeadingOffset, heading_offset: HeadingOffset,
@ -383,19 +384,18 @@ fn document(
/// Render md_text as markdown. /// Render md_text as markdown.
fn render_markdown( fn render_markdown(
w: &mut Buffer, w: &mut Buffer,
cx: &Context<'_>, cx: &mut Context<'_>,
md_text: &str, md_text: &str,
links: Vec<RenderedLink>, links: Vec<RenderedLink>,
heading_offset: HeadingOffset, heading_offset: HeadingOffset,
) { ) {
let mut ids = cx.id_map.borrow_mut();
write!( write!(
w, w,
"<div class=\"docblock\">{}</div>", "<div class=\"docblock\">{}</div>",
Markdown { Markdown {
content: md_text, content: md_text,
links: &links, links: &links,
ids: &mut ids, ids: &mut cx.id_map,
error_codes: cx.shared.codes, error_codes: cx.shared.codes,
edition: cx.shared.edition(), edition: cx.shared.edition(),
playground: &cx.shared.playground, playground: &cx.shared.playground,
@ -410,7 +410,7 @@ fn render_markdown(
fn document_short( fn document_short(
w: &mut Buffer, w: &mut Buffer,
item: &clean::Item, item: &clean::Item,
cx: &Context<'_>, cx: &mut Context<'_>,
link: AssocItemLink<'_>, link: AssocItemLink<'_>,
parent: &clean::Item, parent: &clean::Item,
show_def_docs: bool, show_def_docs: bool,
@ -439,7 +439,7 @@ fn document_short(
fn document_full_collapsible( fn document_full_collapsible(
w: &mut Buffer, w: &mut Buffer,
item: &clean::Item, item: &clean::Item,
cx: &Context<'_>, cx: &mut Context<'_>,
heading_offset: HeadingOffset, heading_offset: HeadingOffset,
) { ) {
document_full_inner(w, item, cx, true, heading_offset); document_full_inner(w, item, cx, true, heading_offset);
@ -448,7 +448,7 @@ fn document_full_collapsible(
fn document_full( fn document_full(
w: &mut Buffer, w: &mut Buffer,
item: &clean::Item, item: &clean::Item,
cx: &Context<'_>, cx: &mut Context<'_>,
heading_offset: HeadingOffset, heading_offset: HeadingOffset,
) { ) {
document_full_inner(w, item, cx, false, heading_offset); document_full_inner(w, item, cx, false, heading_offset);
@ -457,7 +457,7 @@ fn document_full(
fn document_full_inner( fn document_full_inner(
w: &mut Buffer, w: &mut Buffer,
item: &clean::Item, item: &clean::Item,
cx: &Context<'_>, cx: &mut Context<'_>,
is_collapsible: bool, is_collapsible: bool,
heading_offset: HeadingOffset, heading_offset: HeadingOffset,
) { ) {
@ -493,7 +493,7 @@ fn document_full_inner(
/// * Required features (through the `doc_cfg` feature) /// * Required features (through the `doc_cfg` feature)
fn document_item_info( fn document_item_info(
w: &mut Buffer, w: &mut Buffer,
cx: &Context<'_>, cx: &mut Context<'_>,
item: &clean::Item, item: &clean::Item,
parent: Option<&clean::Item>, parent: Option<&clean::Item>,
) { ) {
@ -522,7 +522,7 @@ fn portability(item: &clean::Item, parent: Option<&clean::Item>) -> Option<Strin
/// the item's documentation. /// the item's documentation.
fn short_item_info( fn short_item_info(
item: &clean::Item, item: &clean::Item,
cx: &Context<'_>, cx: &mut Context<'_>,
parent: Option<&clean::Item>, parent: Option<&clean::Item>,
) -> Vec<String> { ) -> Vec<String> {
let mut extra_info = vec![]; let mut extra_info = vec![];
@ -550,10 +550,9 @@ fn short_item_info(
if let Some(note) = note { if let Some(note) = note {
let note = note.as_str(); let note = note.as_str();
let mut ids = cx.id_map.borrow_mut();
let html = MarkdownHtml( let html = MarkdownHtml(
note, note,
&mut ids, &mut cx.id_map,
error_codes, error_codes,
cx.shared.edition(), cx.shared.edition(),
&cx.shared.playground, &cx.shared.playground,
@ -601,7 +600,7 @@ fn short_item_info(
// Render the list of items inside one of the sections "Trait Implementations", // Render the list of items inside one of the sections "Trait Implementations",
// "Auto Trait Implementations," "Blanket Trait Implementations" (on struct/enum pages). // "Auto Trait Implementations," "Blanket Trait Implementations" (on struct/enum pages).
fn render_impls( fn render_impls(
cx: &Context<'_>, cx: &mut Context<'_>,
w: &mut Buffer, w: &mut Buffer,
impls: &[&&Impl], impls: &[&&Impl],
containing_item: &clean::Item, containing_item: &clean::Item,
@ -994,7 +993,7 @@ impl<'a> AssocItemLink<'a> {
fn render_assoc_items( fn render_assoc_items(
w: &mut Buffer, w: &mut Buffer,
cx: &Context<'_>, cx: &mut Context<'_>,
containing_item: &clean::Item, containing_item: &clean::Item,
it: DefId, it: DefId,
what: AssocItemRender<'_>, what: AssocItemRender<'_>,
@ -1006,14 +1005,15 @@ fn render_assoc_items(
fn render_assoc_items_inner( fn render_assoc_items_inner(
w: &mut Buffer, w: &mut Buffer,
cx: &Context<'_>, cx: &mut Context<'_>,
containing_item: &clean::Item, containing_item: &clean::Item,
it: DefId, it: DefId,
what: AssocItemRender<'_>, what: AssocItemRender<'_>,
derefs: &mut FxHashSet<DefId>, derefs: &mut FxHashSet<DefId>,
) { ) {
info!("Documenting associated items of {:?}", containing_item.name); info!("Documenting associated items of {:?}", containing_item.name);
let cache = cx.cache(); let shared = Rc::clone(&cx.shared);
let cache = &shared.cache;
let Some(v) = cache.impls.get(&it) else { return }; let Some(v) = cache.impls.get(&it) else { return };
let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none()); let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none());
if !non_trait.is_empty() { if !non_trait.is_empty() {
@ -1032,7 +1032,7 @@ fn render_assoc_items_inner(
let id = let id =
cx.derive_id(small_url_encode(format!("deref-methods-{:#}", type_.print(cx)))); cx.derive_id(small_url_encode(format!("deref-methods-{:#}", type_.print(cx))));
if let Some(def_id) = type_.def_id(cx.cache()) { if let Some(def_id) = type_.def_id(cx.cache()) {
cx.deref_id_map.borrow_mut().insert(def_id, id.clone()); cx.deref_id_map.insert(def_id, id.clone());
} }
write!( write!(
tmp_buf, tmp_buf,
@ -1138,7 +1138,7 @@ fn render_assoc_items_inner(
fn render_deref_methods( fn render_deref_methods(
w: &mut Buffer, w: &mut Buffer,
cx: &Context<'_>, cx: &mut Context<'_>,
impl_: &Impl, impl_: &Impl,
container_item: &clean::Item, container_item: &clean::Item,
deref_mut: bool, deref_mut: bool,
@ -1285,7 +1285,7 @@ struct ImplRenderingParameters {
fn render_impl( fn render_impl(
w: &mut Buffer, w: &mut Buffer,
cx: &Context<'_>, cx: &mut Context<'_>,
i: &Impl, i: &Impl,
parent: &clean::Item, parent: &clean::Item,
link: AssocItemLink<'_>, link: AssocItemLink<'_>,
@ -1294,7 +1294,8 @@ fn render_impl(
aliases: &[String], aliases: &[String],
rendering_params: ImplRenderingParameters, rendering_params: ImplRenderingParameters,
) { ) {
let cache = cx.cache(); let shared = Rc::clone(&cx.shared);
let cache = &shared.cache;
let traits = &cache.traits; let traits = &cache.traits;
let trait_ = i.trait_did().map(|did| &traits[&did]); let trait_ = i.trait_did().map(|did| &traits[&did]);
let mut close_tags = String::new(); let mut close_tags = String::new();
@ -1307,7 +1308,7 @@ fn render_impl(
fn doc_impl_item( fn doc_impl_item(
boring: &mut Buffer, boring: &mut Buffer,
interesting: &mut Buffer, interesting: &mut Buffer,
cx: &Context<'_>, cx: &mut Context<'_>,
item: &clean::Item, item: &clean::Item,
parent: &clean::Item, parent: &clean::Item,
containing_item: &clean::Item, containing_item: &clean::Item,
@ -1520,7 +1521,7 @@ fn render_impl(
fn render_default_items( fn render_default_items(
boring: &mut Buffer, boring: &mut Buffer,
interesting: &mut Buffer, interesting: &mut Buffer,
cx: &Context<'_>, cx: &mut Context<'_>,
t: &clean::Trait, t: &clean::Trait,
i: &clean::Impl, i: &clean::Impl,
parent: &clean::Item, parent: &clean::Item,
@ -1599,14 +1600,13 @@ fn render_impl(
} }
if let Some(ref dox) = i.impl_item.collapsed_doc_value() { if let Some(ref dox) = i.impl_item.collapsed_doc_value() {
let mut ids = cx.id_map.borrow_mut();
write!( write!(
w, w,
"<div class=\"docblock\">{}</div>", "<div class=\"docblock\">{}</div>",
Markdown { Markdown {
content: &*dox, content: &*dox,
links: &i.impl_item.links(cx), links: &i.impl_item.links(cx),
ids: &mut ids, ids: &mut cx.id_map,
error_codes: cx.shared.codes, error_codes: cx.shared.codes,
edition: cx.shared.edition(), edition: cx.shared.edition(),
playground: &cx.shared.playground, playground: &cx.shared.playground,
@ -1664,7 +1664,7 @@ fn render_rightside(
pub(crate) fn render_impl_summary( pub(crate) fn render_impl_summary(
w: &mut Buffer, w: &mut Buffer,
cx: &Context<'_>, cx: &mut Context<'_>,
i: &Impl, i: &Impl,
parent: &clean::Item, parent: &clean::Item,
containing_item: &clean::Item, containing_item: &clean::Item,
@ -2092,10 +2092,8 @@ fn sidebar_deref_methods(
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
if !ret.is_empty() { if !ret.is_empty() {
let map;
let id = if let Some(target_def_id) = real_target.def_id(c) { let id = if let Some(target_def_id) = real_target.def_id(c) {
map = cx.deref_id_map.borrow(); cx.deref_id_map.get(&target_def_id).expect("Deref section without derived id")
map.get(&target_def_id).expect("Deref section without derived id")
} else { } else {
"deref-methods" "deref-methods"
}; };
@ -2641,14 +2639,14 @@ const MAX_FULL_EXAMPLES: usize = 5;
const NUM_VISIBLE_LINES: usize = 10; const NUM_VISIBLE_LINES: usize = 10;
/// Generates the HTML for example call locations generated via the --scrape-examples flag. /// Generates the HTML for example call locations generated via the --scrape-examples flag.
fn render_call_locations(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item) { fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item) {
let tcx = cx.tcx(); let tcx = cx.tcx();
let def_id = item.item_id.expect_def_id(); let def_id = item.item_id.expect_def_id();
let key = tcx.def_path_hash(def_id); let key = tcx.def_path_hash(def_id);
let Some(call_locations) = cx.shared.call_locations.get(&key) else { return }; let Some(call_locations) = cx.shared.call_locations.get(&key) else { return };
// Generate a unique ID so users can link to this section for a given method // Generate a unique ID so users can link to this section for a given method
let id = cx.id_map.borrow_mut().derive("scraped-examples"); let id = cx.id_map.derive("scraped-examples");
write!( write!(
w, w,
"<div class=\"docblock scraped-example-list\">\ "<div class=\"docblock scraped-example-list\">\

View file

@ -2,6 +2,7 @@ use clean::AttributesExt;
use std::cmp::Ordering; use std::cmp::Ordering;
use std::fmt; use std::fmt;
use std::rc::Rc;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir as hir; use rustc_hir as hir;
@ -60,7 +61,12 @@ struct ItemVars<'a> {
src_href: Option<&'a str>, src_href: Option<&'a str>,
} }
pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer, page: &Page<'_>) { pub(super) fn print_item(
cx: &mut Context<'_>,
item: &clean::Item,
buf: &mut Buffer,
page: &Page<'_>,
) {
debug_assert!(!item.is_stripped()); debug_assert!(!item.is_stripped());
let typ = match *item.kind { let typ = match *item.kind {
clean::ModuleItem(_) => { clean::ModuleItem(_) => {
@ -187,7 +193,7 @@ fn toggle_close(w: &mut Buffer) {
w.write_str("</details>"); w.write_str("</details>");
} }
fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) { fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: &[clean::Item]) {
document(w, cx, item, None, HeadingOffset::H2); document(w, cx, item, None, HeadingOffset::H2);
let mut indices = (0..items.len()).filter(|i| !items[*i].is_stripped()).collect::<Vec<usize>>(); let mut indices = (0..items.len()).filter(|i| !items[*i].is_stripped()).collect::<Vec<usize>>();
@ -344,6 +350,12 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
let add = if stab.is_some() { " " } else { "" }; let add = if stab.is_some() { " " } else { "" };
w.write_str(ITEM_TABLE_ROW_OPEN); w.write_str(ITEM_TABLE_ROW_OPEN);
let id = match import.kind {
clean::ImportKind::Simple(s) => {
format!(" id=\"{}\"", cx.derive_id(format!("reexport.{}", s)))
}
clean::ImportKind::Glob => String::new(),
};
write!( write!(
w, w,
"<div class=\"item-left {stab}{add}import-item\"{id}>\ "<div class=\"item-left {stab}{add}import-item\"{id}>\
@ -351,15 +363,9 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
</div>\ </div>\
<div class=\"item-right docblock-short\">{stab_tags}</div>", <div class=\"item-right docblock-short\">{stab_tags}</div>",
stab = stab.unwrap_or_default(), stab = stab.unwrap_or_default(),
add = add,
vis = myitem.visibility.print_with_space(myitem.item_id, cx), vis = myitem.visibility.print_with_space(myitem.item_id, cx),
imp = import.print(cx), imp = import.print(cx),
stab_tags = stab_tags.unwrap_or_default(), stab_tags = stab_tags.unwrap_or_default(),
id = match import.kind {
clean::ImportKind::Simple(s) =>
format!(" id=\"{}\"", cx.derive_id(format!("reexport.{}", s))),
clean::ImportKind::Glob => String::new(),
},
); );
w.write_str(ITEM_TABLE_ROW_CLOSE); w.write_str(ITEM_TABLE_ROW_CLOSE);
} }
@ -464,7 +470,7 @@ fn extra_info_tags(item: &clean::Item, parent: &clean::Item, tcx: TyCtxt<'_>) ->
tags tags
} }
fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::Function) { fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &clean::Function) {
let header = it.fn_header(cx.tcx()).expect("printing a function which isn't a function"); let header = it.fn_header(cx.tcx()).expect("printing a function which isn't a function");
let constness = print_constness_with_space(&header.constness, it.const_stability(cx.tcx())); let constness = print_constness_with_space(&header.constness, it.const_stability(cx.tcx()));
let unsafety = header.unsafety.print_with_space(); let unsafety = header.unsafety.print_with_space();
@ -507,7 +513,7 @@ fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::
document(w, cx, it, None, HeadingOffset::H2) document(w, cx, it, None, HeadingOffset::H2)
} }
fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Trait) { fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Trait) {
let bounds = bounds(&t.bounds, false, cx); let bounds = bounds(&t.bounds, false, cx);
let required_types = t.items.iter().filter(|m| m.is_ty_associated_type()).collect::<Vec<_>>(); let required_types = t.items.iter().filter(|m| m.is_ty_associated_type()).collect::<Vec<_>>();
let provided_types = t.items.iter().filter(|m| m.is_associated_type()).collect::<Vec<_>>(); let provided_types = t.items.iter().filter(|m| m.is_associated_type()).collect::<Vec<_>>();
@ -674,7 +680,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
) )
} }
fn trait_item(w: &mut Buffer, cx: &Context<'_>, m: &clean::Item, t: &clean::Item) { fn trait_item(w: &mut Buffer, cx: &mut Context<'_>, m: &clean::Item, t: &clean::Item) {
let name = m.name.unwrap(); let name = m.name.unwrap();
info!("Documenting {} on {:?}", name, t.name); info!("Documenting {} on {:?}", name, t.name);
let item_type = m.type_(); let item_type = m.type_();
@ -791,14 +797,15 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
// If there are methods directly on this trait object, render them here. // If there are methods directly on this trait object, render them here.
render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All); render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All);
let cache = cx.cache(); let cloned_shared = Rc::clone(&cx.shared);
let cache = &cloned_shared.cache;
let mut extern_crates = FxHashSet::default(); let mut extern_crates = FxHashSet::default();
if let Some(implementors) = cache.implementors.get(&it.item_id.expect_def_id()) { if let Some(implementors) = cache.implementors.get(&it.item_id.expect_def_id()) {
// The DefId is for the first Type found with that name. The bool is // The DefId is for the first Type found with that name. The bool is
// if any Types with the same name but different DefId have been found. // if any Types with the same name but different DefId have been found.
let mut implementor_dups: FxHashMap<Symbol, (DefId, bool)> = FxHashMap::default(); let mut implementor_dups: FxHashMap<Symbol, (DefId, bool)> = FxHashMap::default();
for implementor in implementors { for implementor in implementors {
if let Some(did) = implementor.inner_impl().for_.without_borrowed_ref().def_id(cx.cache()) && if let Some(did) = implementor.inner_impl().for_.without_borrowed_ref().def_id(cache) &&
!did.is_local() { !did.is_local() {
extern_crates.insert(did.krate); extern_crates.insert(did.krate);
} }
@ -996,7 +1003,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
); );
} }
fn item_trait_alias(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::TraitAlias) { fn item_trait_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::TraitAlias) {
wrap_into_docblock(w, |w| { wrap_into_docblock(w, |w| {
wrap_item(w, "trait-alias", |w| { wrap_item(w, "trait-alias", |w| {
render_attributes_in_pre(w, it, ""); render_attributes_in_pre(w, it, "");
@ -1020,7 +1027,7 @@ fn item_trait_alias(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clea
render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All) render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All)
} }
fn item_opaque_ty(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::OpaqueTy) { fn item_opaque_ty(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::OpaqueTy) {
wrap_into_docblock(w, |w| { wrap_into_docblock(w, |w| {
wrap_item(w, "opaque", |w| { wrap_item(w, "opaque", |w| {
render_attributes_in_pre(w, it, ""); render_attributes_in_pre(w, it, "");
@ -1044,7 +1051,7 @@ fn item_opaque_ty(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean:
render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All) render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All)
} }
fn item_typedef(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Typedef) { fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Typedef) {
fn write_content(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Typedef) { fn write_content(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Typedef) {
wrap_item(w, "typedef", |w| { wrap_item(w, "typedef", |w| {
render_attributes_in_pre(w, it, ""); render_attributes_in_pre(w, it, "");
@ -1073,7 +1080,7 @@ fn item_typedef(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::T
document_type_layout(w, cx, def_id); document_type_layout(w, cx, def_id);
} }
fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Union) { fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Union) {
wrap_into_docblock(w, |w| { wrap_into_docblock(w, |w| {
wrap_item(w, "union", |w| { wrap_item(w, "union", |w| {
render_attributes_in_pre(w, it, ""); render_attributes_in_pre(w, it, "");
@ -1135,7 +1142,7 @@ fn print_tuple_struct_fields(w: &mut Buffer, cx: &Context<'_>, s: &[clean::Item]
} }
} }
fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum) { fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::Enum) {
let count_variants = e.variants().count(); let count_variants = e.variants().count();
wrap_into_docblock(w, |w| { wrap_into_docblock(w, |w| {
wrap_item(w, "enum", |w| { wrap_item(w, "enum", |w| {
@ -1283,7 +1290,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
document_type_layout(w, cx, def_id); document_type_layout(w, cx, def_id);
} }
fn item_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Macro) { fn item_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Macro) {
wrap_into_docblock(w, |w| { wrap_into_docblock(w, |w| {
highlight::render_with_highlighting( highlight::render_with_highlighting(
&t.source, &t.source,
@ -1300,7 +1307,7 @@ fn item_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Mac
document(w, cx, it, None, HeadingOffset::H2) document(w, cx, it, None, HeadingOffset::H2)
} }
fn item_proc_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, m: &clean::ProcMacro) { fn item_proc_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, m: &clean::ProcMacro) {
wrap_into_docblock(w, |w| { wrap_into_docblock(w, |w| {
let name = it.name.expect("proc-macros always have names"); let name = it.name.expect("proc-macros always have names");
match m.kind { match m.kind {
@ -1332,12 +1339,12 @@ fn item_proc_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, m: &clean
document(w, cx, it, None, HeadingOffset::H2) document(w, cx, it, None, HeadingOffset::H2)
} }
fn item_primitive(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) { fn item_primitive(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
document(w, cx, it, None, HeadingOffset::H2); document(w, cx, it, None, HeadingOffset::H2);
render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All) render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All)
} }
fn item_constant(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, c: &clean::Constant) { fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &clean::Constant) {
wrap_into_docblock(w, |w| { wrap_into_docblock(w, |w| {
wrap_item(w, "const", |w| { wrap_item(w, "const", |w| {
render_attributes_in_code(w, it); render_attributes_in_code(w, it);
@ -1377,7 +1384,7 @@ fn item_constant(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, c: &clean::
document(w, cx, it, None, HeadingOffset::H2) document(w, cx, it, None, HeadingOffset::H2)
} }
fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Struct) { fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Struct) {
wrap_into_docblock(w, |w| { wrap_into_docblock(w, |w| {
wrap_item(w, "struct", |w| { wrap_item(w, "struct", |w| {
render_attributes_in_code(w, it); render_attributes_in_code(w, it);
@ -1430,7 +1437,7 @@ fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
document_type_layout(w, cx, def_id); document_type_layout(w, cx, def_id);
} }
fn item_static(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Static) { fn item_static(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Static) {
wrap_into_docblock(w, |w| { wrap_into_docblock(w, |w| {
wrap_item(w, "static", |w| { wrap_item(w, "static", |w| {
render_attributes_in_code(w, it); render_attributes_in_code(w, it);
@ -1447,7 +1454,7 @@ fn item_static(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
document(w, cx, it, None, HeadingOffset::H2) document(w, cx, it, None, HeadingOffset::H2)
} }
fn item_foreign_type(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) { fn item_foreign_type(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
wrap_into_docblock(w, |w| { wrap_into_docblock(w, |w| {
wrap_item(w, "foreigntype", |w| { wrap_item(w, "foreigntype", |w| {
w.write_str("extern {\n"); w.write_str("extern {\n");
@ -1466,7 +1473,7 @@ fn item_foreign_type(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All) render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All)
} }
fn item_keyword(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) { fn item_keyword(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
document(w, cx, it, None, HeadingOffset::H2) document(w, cx, it, None, HeadingOffset::H2)
} }
@ -1579,7 +1586,7 @@ fn compare_impl<'a, 'b>(lhs: &'a &&Impl, rhs: &'b &&Impl, cx: &Context<'_>) -> O
} }
fn render_implementor( fn render_implementor(
cx: &Context<'_>, cx: &mut Context<'_>,
implementor: &Impl, implementor: &Impl,
trait_: &clean::Item, trait_: &clean::Item,
w: &mut Buffer, w: &mut Buffer,

View file

@ -5,6 +5,7 @@ use std::io::prelude::*;
use std::io::{self, BufReader}; use std::io::{self, BufReader};
use std::lazy::SyncLazy as Lazy; use std::lazy::SyncLazy as Lazy;
use std::path::{Component, Path, PathBuf}; use std::path::{Component, Path, PathBuf};
use std::rc::Rc;
use itertools::Itertools; use itertools::Itertools;
use rustc_data_structures::flock; use rustc_data_structures::flock;
@ -135,7 +136,7 @@ impl Context<'_> {
} }
pub(super) fn write_shared( pub(super) fn write_shared(
cx: &Context<'_>, cx: &mut Context<'_>,
krate: &Crate, krate: &Crate,
search_index: String, search_index: String,
options: &RenderOptions, options: &RenderOptions,
@ -462,15 +463,16 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex};
crate::markdown::render(&index_page, md_opts, cx.shared.edition()) crate::markdown::render(&index_page, md_opts, cx.shared.edition())
.map_err(|e| Error::new(e, &index_page))?; .map_err(|e| Error::new(e, &index_page))?;
} else { } else {
let shared = Rc::clone(&cx.shared);
let dst = cx.dst.join("index.html"); let dst = cx.dst.join("index.html");
let page = layout::Page { let page = layout::Page {
title: "Index of crates", title: "Index of crates",
css_class: "mod", css_class: "mod",
root_path: "./", root_path: "./",
static_root_path: cx.shared.static_root_path.as_deref(), static_root_path: shared.static_root_path.as_deref(),
description: "List of crates", description: "List of crates",
keywords: BASIC_KEYWORDS, keywords: BASIC_KEYWORDS,
resource_suffix: &cx.shared.resource_suffix, resource_suffix: &shared.resource_suffix,
extra_scripts: &[], extra_scripts: &[],
static_extra_scripts: &[], static_extra_scripts: &[],
}; };
@ -490,8 +492,8 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex};
}) })
.collect::<String>() .collect::<String>()
); );
let v = layout::render(&cx.shared.layout, &page, "", content, &cx.shared.style_files); let v = layout::render(&shared.layout, &page, "", content, &shared.style_files);
cx.shared.fs.write(dst, v)?; shared.fs.write(dst, v)?;
} }
} }

View file

@ -6,15 +6,18 @@ use crate::html::highlight;
use crate::html::layout; use crate::html::layout;
use crate::html::render::{Context, BASIC_KEYWORDS}; use crate::html::render::{Context, BASIC_KEYWORDS};
use crate::visit::DocVisitor; use crate::visit::DocVisitor;
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir::def_id::LOCAL_CRATE; use rustc_hir::def_id::LOCAL_CRATE;
use rustc_middle::ty::TyCtxt; use rustc_middle::ty::TyCtxt;
use rustc_session::Session; use rustc_session::Session;
use rustc_span::edition::Edition; use rustc_span::edition::Edition;
use rustc_span::source_map::FileName; use rustc_span::source_map::FileName;
use std::ffi::OsStr; use std::ffi::OsStr;
use std::fs; use std::fs;
use std::path::{Component, Path, PathBuf}; use std::path::{Component, Path, PathBuf};
use std::rc::Rc;
pub(crate) fn render(cx: &mut Context<'_>, krate: &clean::Crate) -> Result<(), Error> { pub(crate) fn render(cx: &mut Context<'_>, krate: &clean::Crate) -> Result<(), Error> {
info!("emitting source files"); info!("emitting source files");
@ -174,15 +177,16 @@ impl SourceCollector<'_, '_> {
// Remove the utf-8 BOM if any // Remove the utf-8 BOM if any
let contents = contents.strip_prefix('\u{feff}').unwrap_or(&contents); let contents = contents.strip_prefix('\u{feff}').unwrap_or(&contents);
let shared = Rc::clone(&self.cx.shared);
// Create the intermediate directories // Create the intermediate directories
let mut cur = self.dst.clone(); let mut cur = self.dst.clone();
let mut root_path = String::from("../../"); let mut root_path = String::from("../../");
clean_path(&self.cx.shared.src_root, &p, false, |component| { clean_path(&shared.src_root, &p, false, |component| {
cur.push(component); cur.push(component);
root_path.push_str("../"); root_path.push_str("../");
}); });
self.cx.shared.ensure_dir(&cur)?; shared.ensure_dir(&cur)?;
let src_fname = p.file_name().expect("source has no filename").to_os_string(); let src_fname = p.file_name().expect("source has no filename").to_os_string();
let mut fname = src_fname.clone(); let mut fname = src_fname.clone();
@ -195,32 +199,33 @@ impl SourceCollector<'_, '_> {
title: &title, title: &title,
css_class: "source", css_class: "source",
root_path: &root_path, root_path: &root_path,
static_root_path: self.cx.shared.static_root_path.as_deref(), static_root_path: shared.static_root_path.as_deref(),
description: &desc, description: &desc,
keywords: BASIC_KEYWORDS, keywords: BASIC_KEYWORDS,
resource_suffix: &self.cx.shared.resource_suffix, resource_suffix: &shared.resource_suffix,
extra_scripts: &[&format!("source-files{}", self.cx.shared.resource_suffix)], extra_scripts: &[&format!("source-files{}", shared.resource_suffix)],
static_extra_scripts: &[&format!("source-script{}", self.cx.shared.resource_suffix)], static_extra_scripts: &[&format!("source-script{}", shared.resource_suffix)],
}; };
let v = layout::render( let v = layout::render(
&self.cx.shared.layout, &shared.layout,
&page, &page,
"", "",
|buf: &mut _| { |buf: &mut _| {
let cx = &mut self.cx;
print_src( print_src(
buf, buf,
contents, contents,
self.cx.shared.edition(), cx.shared.edition(),
file_span, file_span,
self.cx, cx,
&root_path, &root_path,
None, None,
SourceContext::Standalone, SourceContext::Standalone,
) )
}, },
&self.cx.shared.style_files, &shared.style_files,
); );
self.cx.shared.fs.write(cur, v)?; shared.fs.write(cur, v)?;
self.emitted_local_sources.insert(p); self.emitted_local_sources.insert(p);
Ok(()) Ok(())
} }