diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index da4273345cb..c5dbf8aa754 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -55,9 +55,9 @@ pub(crate) struct Context<'tcx> { pub(super) render_redirect_pages: bool, /// Tracks section IDs for `Deref` targets so they match in both the main /// body and the sidebar. - pub(super) deref_id_map: RefCell>, + pub(super) deref_id_map: FxHashMap, /// The map used to ensure all generated 'id=' attributes are unique. - pub(super) id_map: RefCell, + pub(super) id_map: IdMap, /// Shared mutable state. /// /// 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. #[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. pub(crate) struct SharedContext<'tcx> { @@ -155,9 +155,8 @@ pub(super) fn sess(&self) -> &'tcx Session { self.shared.tcx.sess } - pub(super) fn derive_id(&self, id: String) -> String { - let mut map = self.id_map.borrow_mut(); - map.derive(id) + pub(super) fn derive_id(&mut self, id: String) -> String { + self.id_map.derive(id) } /// String representation of how to get back to the root path of the 'doc/' @@ -166,7 +165,7 @@ pub(super) fn root_path(&self) -> String { "../".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(); if !is_module { title.push_str(it.name.unwrap().as_str()); @@ -203,23 +202,26 @@ fn render_item(&self, it: &clean::Item, is_module: bool) -> String { }; if !self.render_redirect_pages { + let clone_shared = Rc::clone(&self.shared); let page = layout::Page { css_class: tyname_s, 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, description: &desc, keywords: &keywords, - resource_suffix: &self.shared.resource_suffix, + resource_suffix: &clone_shared.resource_suffix, extra_scripts: &[], static_extra_scripts: &[], }; + let mut page_buffer = Buffer::html(); + print_item(self, it, &mut page_buffer, &page); layout::render( - &self.shared.layout, + &clone_shared.layout, &page, |buf: &mut _| print_sidebar(self, it, buf), - |buf: &mut _| print_item(self, it, buf, &page), - &self.shared.style_files, + move |buf: &mut Buffer| buf.push_buffer(page_buffer), + &clone_shared.style_files, ) } else { if let Some(&(ref names, ty)) = self.cache().paths.get(&it.item_id.expect_def_id()) { @@ -512,8 +514,8 @@ fn init( current: Vec::new(), dst, render_redirect_pages: false, - id_map: RefCell::new(id_map), - deref_id_map: RefCell::new(FxHashMap::default()), + id_map, + deref_id_map: FxHashMap::default(), shared: Rc::new(scx), include_sources, }; @@ -528,7 +530,7 @@ fn init( // Write shared runs within a flock; disable thread dispatching of IO temporarily. 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); } @@ -540,8 +542,8 @@ fn make_child_renderer(&self) -> Self { current: self.current.clone(), dst: self.dst.clone(), render_redirect_pages: self.render_redirect_pages, - deref_id_map: RefCell::new(FxHashMap::default()), - id_map: RefCell::new(IdMap::new()), + deref_id_map: FxHashMap::default(), + id_map: IdMap::new(), shared: Rc::clone(&self.shared), include_sources: self.include_sources, } @@ -557,31 +559,32 @@ fn after_krate(&mut self) -> Result<(), Error> { if !root_path.ends_with('/') { root_path.push('/'); } + let shared = Rc::clone(&self.shared); let mut page = layout::Page { title: "List of all items in this crate", css_class: "mod", 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", keywords: BASIC_KEYWORDS, - resource_suffix: &self.shared.resource_suffix, + resource_suffix: &shared.resource_suffix, 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!("

Crate {}

", crate_name) } else { String::new() }; - let all = self.shared.all.replace(AllTypes::new()); + let all = shared.all.replace(AllTypes::new()); let v = layout::render( - &self.shared.layout, + &shared.layout, &page, sidebar, |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. page.title = "Rustdoc settings"; @@ -590,7 +593,7 @@ fn after_krate(&mut self) -> Result<(), Error> { let sidebar = "

Settings

"; let v = layout::render( - &self.shared.layout, + &shared.layout, &page, sidebar, |buf: &mut Buffer| { @@ -613,33 +616,36 @@ fn after_krate(&mut self) -> Result<(), Error> { 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.description = "How the scraped examples feature works in Rustdoc"; let v = layout::render( - &self.shared.layout, + &shared.layout, &page, "", - scrape_examples_help(&*self.shared), - &self.shared.style_files, + scrape_examples_help(&*shared), + &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() { let redirect_map_path = self.dst.join(crate_name.as_str()).join("redirect-map.json"); let paths = serde_json::to_string(&*redirections.borrow()).unwrap(); - self.shared.ensure_dir(&self.dst.join(crate_name.as_str()))?; - self.shared.fs.write(redirect_map_path, paths)?; + shared.ensure_dir(&self.dst.join(crate_name.as_str()))?; + shared.fs.write(redirect_map_path, paths)?; } } + // No need for it anymore. + drop(shared); + // Flush pending errors. Rc::get_mut(&mut self.shared).unwrap().fs.close(); let nb_errors = @@ -662,7 +668,6 @@ fn mod_item_in(&mut self, item: &clean::Item) -> Result<(), Error> { if !self.render_redirect_pages { self.render_redirect_pages = item.is_stripped(); } - let scx = &self.shared; let item_name = item.name.unwrap(); self.dst.push(&*item_name.as_str()); self.current.push(item_name); @@ -674,7 +679,7 @@ fn mod_item_in(&mut self, item: &clean::Item) -> Result<(), Error> { if !buf.is_empty() { self.shared.ensure_dir(&self.dst)?; 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. @@ -684,7 +689,7 @@ fn mod_item_in(&mut self, item: &clean::Item) -> Result<(), Error> { let items = self.build_sidebar_items(module); let js_dst = self.dst.join(&format!("sidebar-items{}.js", self.shared.resource_suffix)); let v = format!("initSidebarItems({});", serde_json::to_string(&items).unwrap()); - scx.fs.write(js_dst, v)?; + self.shared.fs.write(js_dst, v)?; } Ok(()) } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 3809738cc33..eefb2c2358f 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -42,6 +42,7 @@ use std::fs; use std::iter::Peekable; use std::path::PathBuf; +use std::rc::Rc; use std::str; use std::string::ToString; @@ -364,7 +365,7 @@ fn scrape_examples_help(shared: &SharedContext<'_>) -> String { fn document( w: &mut Buffer, - cx: &Context<'_>, + cx: &mut Context<'_>, item: &clean::Item, parent: Option<&clean::Item>, heading_offset: HeadingOffset, @@ -383,19 +384,18 @@ fn document( /// Render md_text as markdown. fn render_markdown( w: &mut Buffer, - cx: &Context<'_>, + cx: &mut Context<'_>, md_text: &str, links: Vec, heading_offset: HeadingOffset, ) { - let mut ids = cx.id_map.borrow_mut(); write!( w, "
{}
", Markdown { content: md_text, links: &links, - ids: &mut ids, + ids: &mut cx.id_map, error_codes: cx.shared.codes, edition: cx.shared.edition(), playground: &cx.shared.playground, @@ -410,7 +410,7 @@ fn render_markdown( fn document_short( w: &mut Buffer, item: &clean::Item, - cx: &Context<'_>, + cx: &mut Context<'_>, link: AssocItemLink<'_>, parent: &clean::Item, show_def_docs: bool, @@ -439,7 +439,7 @@ fn document_short( fn document_full_collapsible( w: &mut Buffer, item: &clean::Item, - cx: &Context<'_>, + cx: &mut Context<'_>, heading_offset: HeadingOffset, ) { document_full_inner(w, item, cx, true, heading_offset); @@ -448,7 +448,7 @@ fn document_full_collapsible( fn document_full( w: &mut Buffer, item: &clean::Item, - cx: &Context<'_>, + cx: &mut Context<'_>, heading_offset: HeadingOffset, ) { document_full_inner(w, item, cx, false, heading_offset); @@ -457,7 +457,7 @@ fn document_full( fn document_full_inner( w: &mut Buffer, item: &clean::Item, - cx: &Context<'_>, + cx: &mut Context<'_>, is_collapsible: bool, heading_offset: HeadingOffset, ) { @@ -493,7 +493,7 @@ fn document_full_inner( /// * Required features (through the `doc_cfg` feature) fn document_item_info( w: &mut Buffer, - cx: &Context<'_>, + cx: &mut Context<'_>, item: &clean::Item, parent: Option<&clean::Item>, ) { @@ -522,7 +522,7 @@ fn portability(item: &clean::Item, parent: Option<&clean::Item>) -> Option, + cx: &mut Context<'_>, parent: Option<&clean::Item>, ) -> Vec { let mut extra_info = vec![]; @@ -550,10 +550,9 @@ fn short_item_info( if let Some(note) = note { let note = note.as_str(); - let mut ids = cx.id_map.borrow_mut(); let html = MarkdownHtml( note, - &mut ids, + &mut cx.id_map, error_codes, cx.shared.edition(), &cx.shared.playground, @@ -601,7 +600,7 @@ fn short_item_info( // Render the list of items inside one of the sections "Trait Implementations", // "Auto Trait Implementations," "Blanket Trait Implementations" (on struct/enum pages). fn render_impls( - cx: &Context<'_>, + cx: &mut Context<'_>, w: &mut Buffer, impls: &[&&Impl], containing_item: &clean::Item, @@ -994,7 +993,7 @@ fn anchor(&self, id: &'a str) -> Self { fn render_assoc_items( w: &mut Buffer, - cx: &Context<'_>, + cx: &mut Context<'_>, containing_item: &clean::Item, it: DefId, what: AssocItemRender<'_>, @@ -1006,14 +1005,15 @@ fn render_assoc_items( fn render_assoc_items_inner( w: &mut Buffer, - cx: &Context<'_>, + cx: &mut Context<'_>, containing_item: &clean::Item, it: DefId, what: AssocItemRender<'_>, derefs: &mut FxHashSet, ) { 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 (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none()); if !non_trait.is_empty() { @@ -1032,7 +1032,7 @@ fn render_assoc_items_inner( let id = cx.derive_id(small_url_encode(format!("deref-methods-{:#}", type_.print(cx)))); 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!( tmp_buf, @@ -1138,7 +1138,7 @@ fn render_assoc_items_inner( fn render_deref_methods( w: &mut Buffer, - cx: &Context<'_>, + cx: &mut Context<'_>, impl_: &Impl, container_item: &clean::Item, deref_mut: bool, @@ -1285,7 +1285,7 @@ struct ImplRenderingParameters { fn render_impl( w: &mut Buffer, - cx: &Context<'_>, + cx: &mut Context<'_>, i: &Impl, parent: &clean::Item, link: AssocItemLink<'_>, @@ -1294,7 +1294,8 @@ fn render_impl( aliases: &[String], rendering_params: ImplRenderingParameters, ) { - let cache = cx.cache(); + let shared = Rc::clone(&cx.shared); + let cache = &shared.cache; let traits = &cache.traits; let trait_ = i.trait_did().map(|did| &traits[&did]); let mut close_tags = String::new(); @@ -1307,7 +1308,7 @@ fn render_impl( fn doc_impl_item( boring: &mut Buffer, interesting: &mut Buffer, - cx: &Context<'_>, + cx: &mut Context<'_>, item: &clean::Item, parent: &clean::Item, containing_item: &clean::Item, @@ -1520,7 +1521,7 @@ fn doc_impl_item( fn render_default_items( boring: &mut Buffer, interesting: &mut Buffer, - cx: &Context<'_>, + cx: &mut Context<'_>, t: &clean::Trait, i: &clean::Impl, parent: &clean::Item, @@ -1599,14 +1600,13 @@ fn render_default_items( } if let Some(ref dox) = i.impl_item.collapsed_doc_value() { - let mut ids = cx.id_map.borrow_mut(); write!( w, "
{}
", Markdown { content: &*dox, links: &i.impl_item.links(cx), - ids: &mut ids, + ids: &mut cx.id_map, error_codes: cx.shared.codes, edition: cx.shared.edition(), playground: &cx.shared.playground, @@ -1664,7 +1664,7 @@ fn render_rightside( pub(crate) fn render_impl_summary( w: &mut Buffer, - cx: &Context<'_>, + cx: &mut Context<'_>, i: &Impl, parent: &clean::Item, containing_item: &clean::Item, @@ -2092,10 +2092,8 @@ fn sidebar_deref_methods( }) .collect::>(); if !ret.is_empty() { - let map; let id = if let Some(target_def_id) = real_target.def_id(c) { - map = cx.deref_id_map.borrow(); - map.get(&target_def_id).expect("Deref section without derived id") + cx.deref_id_map.get(&target_def_id).expect("Deref section without derived id") } else { "deref-methods" }; @@ -2641,14 +2639,14 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec { const NUM_VISIBLE_LINES: usize = 10; /// 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 def_id = item.item_id.expect_def_id(); let key = tcx.def_path_hash(def_id); 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 - let id = cx.id_map.borrow_mut().derive("scraped-examples"); + let id = cx.id_map.derive("scraped-examples"); write!( w, "
\ diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index ed41b95e73f..dcf36b5e865 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -2,6 +2,7 @@ use std::cmp::Ordering; use std::fmt; +use std::rc::Rc; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir as hir; @@ -60,7 +61,12 @@ struct ItemVars<'a> { 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()); let typ = match *item.kind { clean::ModuleItem(_) => { @@ -187,7 +193,7 @@ fn toggle_close(w: &mut Buffer) { w.write_str(""); } -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); let mut indices = (0..items.len()).filter(|i| !items[*i].is_stripped()).collect::>(); @@ -344,6 +350,12 @@ fn cmp( let add = if stab.is_some() { " " } else { "" }; 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!( w, "
\ @@ -351,15 +363,9 @@ fn cmp(
\
{stab_tags}
", stab = stab.unwrap_or_default(), - add = add, vis = myitem.visibility.print_with_space(myitem.item_id, cx), imp = import.print(cx), 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); } @@ -464,7 +470,7 @@ fn tag_html(class: &str, title: &str, contents: &str) -> String { 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 constness = print_constness_with_space(&header.constness, it.const_stability(cx.tcx())); 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) } -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 required_types = t.items.iter().filter(|m| m.is_ty_associated_type()).collect::>(); let provided_types = t.items.iter().filter(|m| m.is_associated_type()).collect::>(); @@ -674,7 +680,7 @@ fn write_small_section_header(w: &mut Buffer, id: &str, title: &str, extra_conte ) } - 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(); info!("Documenting {} on {:?}", name, t.name); let item_type = m.type_(); @@ -791,14 +797,15 @@ fn trait_item(w: &mut Buffer, cx: &Context<'_>, m: &clean::Item, t: &clean::Item // 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); - let cache = cx.cache(); + let cloned_shared = Rc::clone(&cx.shared); + let cache = &cloned_shared.cache; let mut extern_crates = FxHashSet::default(); 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 // if any Types with the same name but different DefId have been found. let mut implementor_dups: FxHashMap = FxHashMap::default(); 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() { extern_crates.insert(did.krate); } @@ -996,7 +1003,7 @@ fn trait_item(w: &mut Buffer, cx: &Context<'_>, m: &clean::Item, t: &clean::Item ); } -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_item(w, "trait-alias", |w| { 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) } -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_item(w, "opaque", |w| { 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) } -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) { wrap_item(w, "typedef", |w| { render_attributes_in_pre(w, it, ""); @@ -1073,7 +1080,7 @@ fn write_content(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean:: 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_item(w, "union", |w| { 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(); wrap_into_docblock(w, |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); } -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| { highlight::render_with_highlighting( &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) } -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| { let name = it.name.expect("proc-macros always have names"); 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) } -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); 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_item(w, "const", |w| { 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) } -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_item(w, "struct", |w| { 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); } -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_item(w, "static", |w| { 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) } -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_item(w, "foreigntype", |w| { 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) } -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) } @@ -1579,7 +1586,7 @@ fn compare_impl<'a, 'b>(lhs: &'a &&Impl, rhs: &'b &&Impl, cx: &Context<'_>) -> O } fn render_implementor( - cx: &Context<'_>, + cx: &mut Context<'_>, implementor: &Impl, trait_: &clean::Item, w: &mut Buffer, diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index ece659284d1..325d3a31434 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -5,6 +5,7 @@ use std::io::{self, BufReader}; use std::lazy::SyncLazy as Lazy; use std::path::{Component, Path, PathBuf}; +use std::rc::Rc; use itertools::Itertools; use rustc_data_structures::flock; @@ -135,7 +136,7 @@ fn write_minify( } pub(super) fn write_shared( - cx: &Context<'_>, + cx: &mut Context<'_>, krate: &Crate, search_index: String, options: &RenderOptions, @@ -462,15 +463,16 @@ fn to_json_string(&self) -> String { crate::markdown::render(&index_page, md_opts, cx.shared.edition()) .map_err(|e| Error::new(e, &index_page))?; } else { + let shared = Rc::clone(&cx.shared); let dst = cx.dst.join("index.html"); let page = layout::Page { title: "Index of crates", css_class: "mod", 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", keywords: BASIC_KEYWORDS, - resource_suffix: &cx.shared.resource_suffix, + resource_suffix: &shared.resource_suffix, extra_scripts: &[], static_extra_scripts: &[], }; @@ -490,8 +492,8 @@ fn to_json_string(&self) -> String { }) .collect::() ); - let v = layout::render(&cx.shared.layout, &page, "", content, &cx.shared.style_files); - cx.shared.fs.write(dst, v)?; + let v = layout::render(&shared.layout, &page, "", content, &shared.style_files); + shared.fs.write(dst, v)?; } } diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index 0bbdc37ea89..524c90e1f4d 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -6,15 +6,18 @@ use crate::html::layout; use crate::html::render::{Context, BASIC_KEYWORDS}; use crate::visit::DocVisitor; + use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::def_id::LOCAL_CRATE; use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_span::edition::Edition; use rustc_span::source_map::FileName; + use std::ffi::OsStr; use std::fs; use std::path::{Component, Path, PathBuf}; +use std::rc::Rc; pub(crate) fn render(cx: &mut Context<'_>, krate: &clean::Crate) -> Result<(), Error> { info!("emitting source files"); @@ -174,15 +177,16 @@ fn emit_source( // Remove the utf-8 BOM if any let contents = contents.strip_prefix('\u{feff}').unwrap_or(&contents); + let shared = Rc::clone(&self.cx.shared); // Create the intermediate directories let mut cur = self.dst.clone(); 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); 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 mut fname = src_fname.clone(); @@ -195,32 +199,33 @@ fn emit_source( title: &title, css_class: "source", 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, keywords: BASIC_KEYWORDS, - resource_suffix: &self.cx.shared.resource_suffix, - extra_scripts: &[&format!("source-files{}", self.cx.shared.resource_suffix)], - static_extra_scripts: &[&format!("source-script{}", self.cx.shared.resource_suffix)], + resource_suffix: &shared.resource_suffix, + extra_scripts: &[&format!("source-files{}", shared.resource_suffix)], + static_extra_scripts: &[&format!("source-script{}", shared.resource_suffix)], }; let v = layout::render( - &self.cx.shared.layout, + &shared.layout, &page, "", |buf: &mut _| { + let cx = &mut self.cx; print_src( buf, contents, - self.cx.shared.edition(), + cx.shared.edition(), file_span, - self.cx, + cx, &root_path, None, 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); Ok(()) }