mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-23 04:14:28 +00:00
Auto merge of #133345 - GuillaumeGomez:stop-cloning-context, r=notriddle,aDotInTheVoid
Stop cloning `Context` so much This is a first step for https://github.com/rust-lang/rust/issues/82381. It's already big enough so I'll continue in a follow-up once this PR is merged. Next step will be to get rid of `SharedContext` by inlining it directly into `Context`. cc `@camelid` r? `@notriddle`
This commit is contained in:
commit
a522d78598
@ -1,5 +1,5 @@
|
||||
use rustc_data_structures::profiling::SelfProfilerRef;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use tracing::debug;
|
||||
|
||||
use crate::clean;
|
||||
use crate::config::RenderOptions;
|
||||
@ -17,6 +17,18 @@ pub(crate) trait FormatRenderer<'tcx>: Sized {
|
||||
///
|
||||
/// This is true for html, and false for json. See #80664
|
||||
const RUN_ON_MODULE: bool;
|
||||
/// This associated type is the type where the current module information is stored.
|
||||
///
|
||||
/// For each module, we go through their items by calling for each item:
|
||||
///
|
||||
/// 1. save_module_data
|
||||
/// 2. item
|
||||
/// 3. set_back_info
|
||||
///
|
||||
/// However,the `item` method might update information in `self` (for example if the child is
|
||||
/// a module). To prevent it to impact the other children of the current module, we need to
|
||||
/// reset the information between each call to `item` by using `set_back_info`.
|
||||
type ModuleData;
|
||||
|
||||
/// Sets up any state required for the renderer. When this is called the cache has already been
|
||||
/// populated.
|
||||
@ -27,8 +39,20 @@ pub(crate) trait FormatRenderer<'tcx>: Sized {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
) -> Result<(Self, clean::Crate), Error>;
|
||||
|
||||
/// Make a new renderer to render a child of the item currently being rendered.
|
||||
fn make_child_renderer(&self) -> Self;
|
||||
/// This method is called right before call [`Self::item`]. This method returns a type
|
||||
/// containing information that needs to be reset after the [`Self::item`] method has been
|
||||
/// called with the [`Self::set_back_info`] method.
|
||||
///
|
||||
/// In short it goes like this:
|
||||
///
|
||||
/// ```ignore (not valid code)
|
||||
/// let reset_data = type.save_module_data();
|
||||
/// type.item(item)?;
|
||||
/// type.set_back_info(reset_data);
|
||||
/// ```
|
||||
fn save_module_data(&mut self) -> Self::ModuleData;
|
||||
/// Used to reset current module's information.
|
||||
fn set_back_info(&mut self, info: Self::ModuleData);
|
||||
|
||||
/// Renders a single non-module item. This means no recursive sub-item rendering is required.
|
||||
fn item(&mut self, item: clean::Item) -> Result<(), Error>;
|
||||
@ -47,6 +71,40 @@ pub(crate) trait FormatRenderer<'tcx>: Sized {
|
||||
fn cache(&self) -> &Cache;
|
||||
}
|
||||
|
||||
fn run_format_inner<'tcx, T: FormatRenderer<'tcx>>(
|
||||
cx: &mut T,
|
||||
item: clean::Item,
|
||||
prof: &SelfProfilerRef,
|
||||
) -> Result<(), Error> {
|
||||
if item.is_mod() && T::RUN_ON_MODULE {
|
||||
// modules are special because they add a namespace. We also need to
|
||||
// recurse into the items of the module as well.
|
||||
let _timer =
|
||||
prof.generic_activity_with_arg("render_mod_item", item.name.unwrap().to_string());
|
||||
|
||||
cx.mod_item_in(&item)?;
|
||||
let (clean::StrippedItem(box clean::ModuleItem(module)) | clean::ModuleItem(module)) =
|
||||
item.inner.kind
|
||||
else {
|
||||
unreachable!()
|
||||
};
|
||||
for it in module.items {
|
||||
let info = cx.save_module_data();
|
||||
run_format_inner(cx, it, prof)?;
|
||||
cx.set_back_info(info);
|
||||
}
|
||||
|
||||
cx.mod_item_out()?;
|
||||
// FIXME: checking `item.name.is_some()` is very implicit and leads to lots of special
|
||||
// cases. Use an explicit match instead.
|
||||
} else if let Some(item_name) = item.name
|
||||
&& !item.is_extern_crate()
|
||||
{
|
||||
prof.generic_activity_with_arg("render_item", item_name.as_str()).run(|| cx.item(item))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Main method for rendering a crate.
|
||||
pub(crate) fn run_format<'tcx, T: FormatRenderer<'tcx>>(
|
||||
krate: clean::Crate,
|
||||
@ -66,36 +124,8 @@ pub(crate) fn run_format<'tcx, T: FormatRenderer<'tcx>>(
|
||||
}
|
||||
|
||||
// Render the crate documentation
|
||||
let mut work = vec![(format_renderer.make_child_renderer(), krate.module)];
|
||||
run_format_inner(&mut format_renderer, krate.module, prof)?;
|
||||
|
||||
while let Some((mut cx, item)) = work.pop() {
|
||||
if item.is_mod() && T::RUN_ON_MODULE {
|
||||
// modules are special because they add a namespace. We also need to
|
||||
// recurse into the items of the module as well.
|
||||
let _timer =
|
||||
prof.generic_activity_with_arg("render_mod_item", item.name.unwrap().to_string());
|
||||
|
||||
cx.mod_item_in(&item)?;
|
||||
let (clean::StrippedItem(box clean::ModuleItem(module)) | clean::ModuleItem(module)) =
|
||||
item.inner.kind
|
||||
else {
|
||||
unreachable!()
|
||||
};
|
||||
for it in module.items {
|
||||
debug!("Adding {:?} to worklist", it.name);
|
||||
work.push((cx.make_child_renderer(), it));
|
||||
}
|
||||
|
||||
cx.mod_item_out()?;
|
||||
// FIXME: checking `item.name.is_some()` is very implicit and leads to lots of special
|
||||
// cases. Use an explicit match instead.
|
||||
} else if let Some(item_name) = item.name
|
||||
&& !item.is_extern_crate()
|
||||
{
|
||||
prof.generic_activity_with_arg("render_item", item_name.as_str())
|
||||
.run(|| cx.item(item))?;
|
||||
}
|
||||
}
|
||||
prof.verbose_generic_activity_with_arg("renderer_after_krate", T::descr())
|
||||
.run(|| format_renderer.after_krate())
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ use std::sync::OnceLock;
|
||||
use pulldown_cmark::{
|
||||
BrokenLink, CodeBlockKind, CowStr, Event, LinkType, Options, Parser, Tag, TagEnd, html,
|
||||
};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_errors::{Diag, DiagMessage};
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
@ -1886,71 +1886,81 @@ pub struct IdMap {
|
||||
existing_footnotes: usize,
|
||||
}
|
||||
|
||||
// The map is pre-initialized and cloned each time to avoid reinitializing it repeatedly.
|
||||
static DEFAULT_ID_MAP: OnceLock<FxHashMap<Cow<'static, str>, usize>> = OnceLock::new();
|
||||
// The map is pre-initialized and then can be used as is to prevent cloning it for each item
|
||||
// (in the sidebar rendering).
|
||||
static DEFAULT_ID_MAP: OnceLock<FxHashSet<&'static str>> = OnceLock::new();
|
||||
|
||||
fn init_id_map() -> FxHashMap<Cow<'static, str>, usize> {
|
||||
let mut map = FxHashMap::default();
|
||||
fn init_id_map() -> FxHashSet<&'static str> {
|
||||
let mut map = FxHashSet::default();
|
||||
// This is the list of IDs used in JavaScript.
|
||||
map.insert("help".into(), 1);
|
||||
map.insert("settings".into(), 1);
|
||||
map.insert("not-displayed".into(), 1);
|
||||
map.insert("alternative-display".into(), 1);
|
||||
map.insert("search".into(), 1);
|
||||
map.insert("crate-search".into(), 1);
|
||||
map.insert("crate-search-div".into(), 1);
|
||||
map.insert("help");
|
||||
map.insert("settings");
|
||||
map.insert("not-displayed");
|
||||
map.insert("alternative-display");
|
||||
map.insert("search");
|
||||
map.insert("crate-search");
|
||||
map.insert("crate-search-div");
|
||||
// This is the list of IDs used in HTML generated in Rust (including the ones
|
||||
// used in tera template files).
|
||||
map.insert("themeStyle".into(), 1);
|
||||
map.insert("settings-menu".into(), 1);
|
||||
map.insert("help-button".into(), 1);
|
||||
map.insert("sidebar-button".into(), 1);
|
||||
map.insert("main-content".into(), 1);
|
||||
map.insert("toggle-all-docs".into(), 1);
|
||||
map.insert("all-types".into(), 1);
|
||||
map.insert("default-settings".into(), 1);
|
||||
map.insert("sidebar-vars".into(), 1);
|
||||
map.insert("copy-path".into(), 1);
|
||||
map.insert("rustdoc-toc".into(), 1);
|
||||
map.insert("rustdoc-modnav".into(), 1);
|
||||
map.insert("themeStyle");
|
||||
map.insert("settings-menu");
|
||||
map.insert("help-button");
|
||||
map.insert("sidebar-button");
|
||||
map.insert("main-content");
|
||||
map.insert("toggle-all-docs");
|
||||
map.insert("all-types");
|
||||
map.insert("default-settings");
|
||||
map.insert("sidebar-vars");
|
||||
map.insert("copy-path");
|
||||
map.insert("rustdoc-toc");
|
||||
map.insert("rustdoc-modnav");
|
||||
// This is the list of IDs used by rustdoc sections (but still generated by
|
||||
// rustdoc).
|
||||
map.insert("fields".into(), 1);
|
||||
map.insert("variants".into(), 1);
|
||||
map.insert("implementors-list".into(), 1);
|
||||
map.insert("synthetic-implementors-list".into(), 1);
|
||||
map.insert("foreign-impls".into(), 1);
|
||||
map.insert("implementations".into(), 1);
|
||||
map.insert("trait-implementations".into(), 1);
|
||||
map.insert("synthetic-implementations".into(), 1);
|
||||
map.insert("blanket-implementations".into(), 1);
|
||||
map.insert("required-associated-types".into(), 1);
|
||||
map.insert("provided-associated-types".into(), 1);
|
||||
map.insert("provided-associated-consts".into(), 1);
|
||||
map.insert("required-associated-consts".into(), 1);
|
||||
map.insert("required-methods".into(), 1);
|
||||
map.insert("provided-methods".into(), 1);
|
||||
map.insert("dyn-compatibility".into(), 1);
|
||||
map.insert("implementors".into(), 1);
|
||||
map.insert("synthetic-implementors".into(), 1);
|
||||
map.insert("implementations-list".into(), 1);
|
||||
map.insert("trait-implementations-list".into(), 1);
|
||||
map.insert("synthetic-implementations-list".into(), 1);
|
||||
map.insert("blanket-implementations-list".into(), 1);
|
||||
map.insert("deref-methods".into(), 1);
|
||||
map.insert("layout".into(), 1);
|
||||
map.insert("aliased-type".into(), 1);
|
||||
map.insert("fields");
|
||||
map.insert("variants");
|
||||
map.insert("implementors-list");
|
||||
map.insert("synthetic-implementors-list");
|
||||
map.insert("foreign-impls");
|
||||
map.insert("implementations");
|
||||
map.insert("trait-implementations");
|
||||
map.insert("synthetic-implementations");
|
||||
map.insert("blanket-implementations");
|
||||
map.insert("required-associated-types");
|
||||
map.insert("provided-associated-types");
|
||||
map.insert("provided-associated-consts");
|
||||
map.insert("required-associated-consts");
|
||||
map.insert("required-methods");
|
||||
map.insert("provided-methods");
|
||||
map.insert("dyn-compatibility");
|
||||
map.insert("implementors");
|
||||
map.insert("synthetic-implementors");
|
||||
map.insert("implementations-list");
|
||||
map.insert("trait-implementations-list");
|
||||
map.insert("synthetic-implementations-list");
|
||||
map.insert("blanket-implementations-list");
|
||||
map.insert("deref-methods");
|
||||
map.insert("layout");
|
||||
map.insert("aliased-type");
|
||||
map
|
||||
}
|
||||
|
||||
impl IdMap {
|
||||
pub fn new() -> Self {
|
||||
IdMap { map: DEFAULT_ID_MAP.get_or_init(init_id_map).clone(), existing_footnotes: 0 }
|
||||
IdMap { map: FxHashMap::default(), existing_footnotes: 0 }
|
||||
}
|
||||
|
||||
pub(crate) fn derive<S: AsRef<str> + ToString>(&mut self, candidate: S) -> String {
|
||||
let id = match self.map.get_mut(candidate.as_ref()) {
|
||||
None => candidate.to_string(),
|
||||
None => {
|
||||
let candidate = candidate.to_string();
|
||||
if DEFAULT_ID_MAP.get_or_init(init_id_map).contains(candidate.as_str()) {
|
||||
let id = format!("{}-{}", candidate, 1);
|
||||
self.map.insert(candidate.into(), 2);
|
||||
id
|
||||
} else {
|
||||
candidate
|
||||
}
|
||||
}
|
||||
Some(a) => {
|
||||
let id = format!("{}-{}", candidate.as_ref(), *a);
|
||||
*a += 1;
|
||||
@ -1970,4 +1980,9 @@ impl IdMap {
|
||||
closure(self, &mut existing_footnotes);
|
||||
self.existing_footnotes = existing_footnotes;
|
||||
}
|
||||
|
||||
pub(crate) fn clear(&mut self) {
|
||||
self.map.clear();
|
||||
self.existing_footnotes = 0;
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ use std::cell::RefCell;
|
||||
use std::collections::BTreeMap;
|
||||
use std::io;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::rc::Rc;
|
||||
use std::sync::mpsc::{Receiver, channel};
|
||||
|
||||
use rinja::Template;
|
||||
@ -49,36 +48,49 @@ pub(crate) struct Context<'tcx> {
|
||||
/// The current destination folder of where HTML artifacts should be placed.
|
||||
/// This changes as the context descends into the module hierarchy.
|
||||
pub(crate) dst: PathBuf,
|
||||
/// A flag, which when `true`, will render pages which redirect to the
|
||||
/// real location of an item. This is used to allow external links to
|
||||
/// publicly reused items to redirect to the right location.
|
||||
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: DefIdMap<String>,
|
||||
pub(super) deref_id_map: RefCell<DefIdMap<String>>,
|
||||
/// The map used to ensure all generated 'id=' attributes are unique.
|
||||
pub(super) id_map: IdMap,
|
||||
pub(super) id_map: RefCell<IdMap>,
|
||||
/// Shared mutable state.
|
||||
///
|
||||
/// Issue for improving the situation: [#82381][]
|
||||
///
|
||||
/// [#82381]: https://github.com/rust-lang/rust/issues/82381
|
||||
pub(crate) shared: Rc<SharedContext<'tcx>>,
|
||||
pub(crate) shared: SharedContext<'tcx>,
|
||||
/// Collection of all types with notable traits referenced in the current module.
|
||||
pub(crate) types_with_notable_traits: RefCell<FxIndexSet<clean::Type>>,
|
||||
/// Contains information that needs to be saved and reset after rendering an item which is
|
||||
/// not a module.
|
||||
pub(crate) info: ContextInfo,
|
||||
}
|
||||
|
||||
/// This struct contains the information that needs to be reset between each
|
||||
/// [`FormatRenderer::item`] call.
|
||||
///
|
||||
/// When we enter a new module, we set these values for the whole module but they might be updated
|
||||
/// in each child item (especially if it's a module). So to prevent these changes to impact other
|
||||
/// items rendering in the same module, we need to reset them to the module's set values.
|
||||
#[derive(Clone, Copy)]
|
||||
pub(crate) struct ContextInfo {
|
||||
/// A flag, which when `true`, will render pages which redirect to the
|
||||
/// real location of an item. This is used to allow external links to
|
||||
/// publicly reused items to redirect to the right location.
|
||||
pub(super) render_redirect_pages: bool,
|
||||
/// This flag indicates whether source links should be generated or not. If
|
||||
/// the source files are present in the html rendering, then this will be
|
||||
/// `true`.
|
||||
pub(crate) include_sources: bool,
|
||||
/// Collection of all types with notable traits referenced in the current module.
|
||||
pub(crate) types_with_notable_traits: FxIndexSet<clean::Type>,
|
||||
/// Field used during rendering, to know if we're inside an inlined item.
|
||||
pub(crate) is_inside_inlined_module: bool,
|
||||
}
|
||||
|
||||
// `Context` is cloned a lot, so we don't want the size to grow unexpectedly.
|
||||
#[cfg(all(not(windows), target_pointer_width = "64"))]
|
||||
rustc_data_structures::static_assert_size!(Context<'_>, 192);
|
||||
#[cfg(all(windows, target_pointer_width = "64"))]
|
||||
rustc_data_structures::static_assert_size!(Context<'_>, 200);
|
||||
impl ContextInfo {
|
||||
fn new(include_sources: bool) -> Self {
|
||||
Self { render_redirect_pages: false, include_sources, is_inside_inlined_module: false }
|
||||
}
|
||||
}
|
||||
|
||||
/// Shared mutable state used in [`Context`] and elsewhere.
|
||||
pub(crate) struct SharedContext<'tcx> {
|
||||
@ -163,8 +175,8 @@ impl<'tcx> Context<'tcx> {
|
||||
self.shared.tcx.sess
|
||||
}
|
||||
|
||||
pub(super) fn derive_id<S: AsRef<str> + ToString>(&mut self, id: S) -> String {
|
||||
self.id_map.derive(id)
|
||||
pub(super) fn derive_id<S: AsRef<str> + ToString>(&self, id: S) -> String {
|
||||
self.id_map.borrow_mut().derive(id)
|
||||
}
|
||||
|
||||
/// String representation of how to get back to the root path of the 'doc/'
|
||||
@ -174,14 +186,16 @@ impl<'tcx> Context<'tcx> {
|
||||
}
|
||||
|
||||
fn render_item(&mut self, it: &clean::Item, is_module: bool) -> String {
|
||||
let mut render_redirect_pages = self.render_redirect_pages;
|
||||
let mut render_redirect_pages = self.info.render_redirect_pages;
|
||||
// If the item is stripped but inlined, links won't point to the item so no need to generate
|
||||
// a file for it.
|
||||
if it.is_stripped()
|
||||
&& let Some(def_id) = it.def_id()
|
||||
&& def_id.is_local()
|
||||
{
|
||||
if self.is_inside_inlined_module || self.shared.cache.inlined_items.contains(&def_id) {
|
||||
if self.info.is_inside_inlined_module
|
||||
|| self.shared.cache.inlined_items.contains(&def_id)
|
||||
{
|
||||
// For now we're forced to generate a redirect page for stripped items until
|
||||
// `record_extern_fqn` correctly points to external items.
|
||||
render_redirect_pages = true;
|
||||
@ -221,24 +235,23 @@ impl<'tcx> Context<'tcx> {
|
||||
};
|
||||
|
||||
if !render_redirect_pages {
|
||||
let clone_shared = Rc::clone(&self.shared);
|
||||
let mut page_buffer = Buffer::html();
|
||||
print_item(self, it, &mut page_buffer);
|
||||
let page = layout::Page {
|
||||
css_class: tyname_s,
|
||||
root_path: &self.root_path(),
|
||||
static_root_path: clone_shared.static_root_path.as_deref(),
|
||||
static_root_path: self.shared.static_root_path.as_deref(),
|
||||
title: &title,
|
||||
description: &desc,
|
||||
resource_suffix: &clone_shared.resource_suffix,
|
||||
resource_suffix: &self.shared.resource_suffix,
|
||||
rust_logo: has_doc_flag(self.tcx(), LOCAL_CRATE.as_def_id(), sym::rust_logo),
|
||||
};
|
||||
let mut page_buffer = Buffer::html();
|
||||
print_item(self, it, &mut page_buffer);
|
||||
layout::render(
|
||||
&clone_shared.layout,
|
||||
&self.shared.layout,
|
||||
&page,
|
||||
|buf: &mut _| print_sidebar(self, it, buf),
|
||||
move |buf: &mut Buffer| buf.push_buffer(page_buffer),
|
||||
&clone_shared.style_files,
|
||||
&self.shared.style_files,
|
||||
)
|
||||
} else {
|
||||
if let Some(&(ref names, ty)) = self.cache().paths.get(&it.item_id.expect_def_id()) {
|
||||
@ -441,6 +454,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
|
||||
}
|
||||
|
||||
const RUN_ON_MODULE: bool = true;
|
||||
type ModuleData = ContextInfo;
|
||||
|
||||
fn init(
|
||||
krate: clean::Crate,
|
||||
@ -562,13 +576,11 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
|
||||
let mut cx = Context {
|
||||
current: Vec::new(),
|
||||
dst,
|
||||
render_redirect_pages: false,
|
||||
id_map,
|
||||
id_map: RefCell::new(id_map),
|
||||
deref_id_map: Default::default(),
|
||||
shared: Rc::new(scx),
|
||||
include_sources,
|
||||
types_with_notable_traits: FxIndexSet::default(),
|
||||
is_inside_inlined_module: false,
|
||||
shared: scx,
|
||||
types_with_notable_traits: RefCell::new(FxIndexSet::default()),
|
||||
info: ContextInfo::new(include_sources),
|
||||
};
|
||||
|
||||
if emit_crate {
|
||||
@ -582,18 +594,15 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
|
||||
Ok((cx, krate))
|
||||
}
|
||||
|
||||
fn make_child_renderer(&self) -> Self {
|
||||
Self {
|
||||
current: self.current.clone(),
|
||||
dst: self.dst.clone(),
|
||||
render_redirect_pages: self.render_redirect_pages,
|
||||
deref_id_map: Default::default(),
|
||||
id_map: IdMap::new(),
|
||||
shared: Rc::clone(&self.shared),
|
||||
include_sources: self.include_sources,
|
||||
types_with_notable_traits: FxIndexSet::default(),
|
||||
is_inside_inlined_module: self.is_inside_inlined_module,
|
||||
}
|
||||
fn save_module_data(&mut self) -> Self::ModuleData {
|
||||
self.deref_id_map.borrow_mut().clear();
|
||||
self.id_map.borrow_mut().clear();
|
||||
self.types_with_notable_traits.borrow_mut().clear();
|
||||
self.info
|
||||
}
|
||||
|
||||
fn set_back_info(&mut self, info: Self::ModuleData) {
|
||||
self.info = info;
|
||||
}
|
||||
|
||||
fn after_krate(&mut self) -> Result<(), Error> {
|
||||
@ -607,7 +616,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
|
||||
if !root_path.ends_with('/') {
|
||||
root_path.push('/');
|
||||
}
|
||||
let shared = Rc::clone(&self.shared);
|
||||
let shared = &self.shared;
|
||||
let mut page = layout::Page {
|
||||
title: "List of all items in this crate",
|
||||
css_class: "mod sys",
|
||||
@ -754,11 +763,8 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
|
||||
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();
|
||||
self.shared.fs.close();
|
||||
let nb_errors = self.shared.errors.iter().map(|err| self.tcx().dcx().err(err)).count();
|
||||
if nb_errors > 0 {
|
||||
Err(Error::new(io::Error::new(io::ErrorKind::Other, "I/O error"), ""))
|
||||
@ -775,8 +781,8 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
|
||||
// External crates will provide links to these structures, so
|
||||
// these modules are recursed into, but not rendered normally
|
||||
// (a flag on the context).
|
||||
if !self.render_redirect_pages {
|
||||
self.render_redirect_pages = item.is_stripped();
|
||||
if !self.info.render_redirect_pages {
|
||||
self.info.render_redirect_pages = item.is_stripped();
|
||||
}
|
||||
let item_name = item.name.unwrap();
|
||||
self.dst.push(item_name.as_str());
|
||||
@ -793,19 +799,19 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
|
||||
self.shared.fs.write(joint_dst, buf)?;
|
||||
}
|
||||
}
|
||||
if !self.is_inside_inlined_module {
|
||||
if !self.info.is_inside_inlined_module {
|
||||
if let Some(def_id) = item.def_id()
|
||||
&& self.cache().inlined_items.contains(&def_id)
|
||||
{
|
||||
self.is_inside_inlined_module = true;
|
||||
self.info.is_inside_inlined_module = true;
|
||||
}
|
||||
} else if !self.cache().document_hidden && item.is_doc_hidden() {
|
||||
// We're not inside an inlined module anymore since this one cannot be re-exported.
|
||||
self.is_inside_inlined_module = false;
|
||||
self.info.is_inside_inlined_module = false;
|
||||
}
|
||||
|
||||
// Render sidebar-items.js used throughout this module.
|
||||
if !self.render_redirect_pages {
|
||||
if !self.info.render_redirect_pages {
|
||||
let (clean::StrippedItem(box clean::ModuleItem(ref module))
|
||||
| clean::ModuleItem(ref module)) = item.kind
|
||||
else {
|
||||
@ -836,8 +842,8 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
|
||||
// External crates will provide links to these structures, so
|
||||
// these modules are recursed into, but not rendered normally
|
||||
// (a flag on the context).
|
||||
if !self.render_redirect_pages {
|
||||
self.render_redirect_pages = item.is_stripped();
|
||||
if !self.info.render_redirect_pages {
|
||||
self.info.render_redirect_pages = item.is_stripped();
|
||||
}
|
||||
|
||||
let buf = self.render_item(&item, false);
|
||||
@ -850,7 +856,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
|
||||
let joint_dst = self.dst.join(file_name);
|
||||
self.shared.fs.write(joint_dst, buf)?;
|
||||
|
||||
if !self.render_redirect_pages {
|
||||
if !self.info.render_redirect_pages {
|
||||
self.shared.all.borrow_mut().append(full_path(self, &item), &item_type);
|
||||
}
|
||||
// If the item is a macro, redirect from the old macro URL (with !)
|
||||
|
@ -41,7 +41,6 @@ use std::collections::VecDeque;
|
||||
use std::fmt::{self, Write};
|
||||
use std::iter::Peekable;
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
use std::{fs, str};
|
||||
|
||||
use rinja::Template;
|
||||
@ -504,7 +503,7 @@ fn scrape_examples_help(shared: &SharedContext<'_>) -> String {
|
||||
}
|
||||
|
||||
fn document<'a, 'cx: 'a>(
|
||||
cx: &'a mut Context<'cx>,
|
||||
cx: &'a Context<'cx>,
|
||||
item: &'a clean::Item,
|
||||
parent: Option<&'a clean::Item>,
|
||||
heading_offset: HeadingOffset,
|
||||
@ -525,7 +524,7 @@ fn document<'a, 'cx: 'a>(
|
||||
|
||||
/// Render md_text as markdown.
|
||||
fn render_markdown<'a, 'cx: 'a>(
|
||||
cx: &'a mut Context<'cx>,
|
||||
cx: &'a Context<'cx>,
|
||||
md_text: &'a str,
|
||||
links: Vec<RenderedLink>,
|
||||
heading_offset: HeadingOffset,
|
||||
@ -537,7 +536,7 @@ fn render_markdown<'a, 'cx: 'a>(
|
||||
Markdown {
|
||||
content: md_text,
|
||||
links: &links,
|
||||
ids: &mut cx.id_map,
|
||||
ids: &mut cx.id_map.borrow_mut(),
|
||||
error_codes: cx.shared.codes,
|
||||
edition: cx.shared.edition(),
|
||||
playground: &cx.shared.playground,
|
||||
@ -552,7 +551,7 @@ fn render_markdown<'a, 'cx: 'a>(
|
||||
/// docs are longer, a "Read more" link is appended to the end.
|
||||
fn document_short<'a, 'cx: 'a>(
|
||||
item: &'a clean::Item,
|
||||
cx: &'a mut Context<'cx>,
|
||||
cx: &'a Context<'cx>,
|
||||
link: AssocItemLink<'a>,
|
||||
parent: &'a clean::Item,
|
||||
show_def_docs: bool,
|
||||
@ -585,7 +584,7 @@ fn document_short<'a, 'cx: 'a>(
|
||||
|
||||
fn document_full_collapsible<'a, 'cx: 'a>(
|
||||
item: &'a clean::Item,
|
||||
cx: &'a mut Context<'cx>,
|
||||
cx: &'a Context<'cx>,
|
||||
heading_offset: HeadingOffset,
|
||||
) -> impl fmt::Display + 'a + Captures<'cx> {
|
||||
document_full_inner(item, cx, true, heading_offset)
|
||||
@ -593,7 +592,7 @@ fn document_full_collapsible<'a, 'cx: 'a>(
|
||||
|
||||
fn document_full<'a, 'cx: 'a>(
|
||||
item: &'a clean::Item,
|
||||
cx: &'a mut Context<'cx>,
|
||||
cx: &'a Context<'cx>,
|
||||
heading_offset: HeadingOffset,
|
||||
) -> impl fmt::Display + 'a + Captures<'cx> {
|
||||
document_full_inner(item, cx, false, heading_offset)
|
||||
@ -601,7 +600,7 @@ fn document_full<'a, 'cx: 'a>(
|
||||
|
||||
fn document_full_inner<'a, 'cx: 'a>(
|
||||
item: &'a clean::Item,
|
||||
cx: &'a mut Context<'cx>,
|
||||
cx: &'a Context<'cx>,
|
||||
is_collapsible: bool,
|
||||
heading_offset: HeadingOffset,
|
||||
) -> impl fmt::Display + 'a + Captures<'cx> {
|
||||
@ -644,7 +643,7 @@ struct ItemInfo {
|
||||
/// * Deprecated
|
||||
/// * Required features (through the `doc_cfg` feature)
|
||||
fn document_item_info(
|
||||
cx: &mut Context<'_>,
|
||||
cx: &Context<'_>,
|
||||
item: &clean::Item,
|
||||
parent: Option<&clean::Item>,
|
||||
) -> ItemInfo {
|
||||
@ -690,7 +689,7 @@ enum ShortItemInfo {
|
||||
/// the item's documentation.
|
||||
fn short_item_info(
|
||||
item: &clean::Item,
|
||||
cx: &mut Context<'_>,
|
||||
cx: &Context<'_>,
|
||||
parent: Option<&clean::Item>,
|
||||
) -> Vec<ShortItemInfo> {
|
||||
let mut extra_info = vec![];
|
||||
@ -715,7 +714,8 @@ fn short_item_info(
|
||||
|
||||
if let Some(note) = note {
|
||||
let note = note.as_str();
|
||||
let html = MarkdownItemInfo(note, &mut cx.id_map);
|
||||
let mut id_map = cx.id_map.borrow_mut();
|
||||
let html = MarkdownItemInfo(note, &mut id_map);
|
||||
message.push_str(": ");
|
||||
message.push_str(&html.into_string());
|
||||
}
|
||||
@ -749,18 +749,17 @@ 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).
|
||||
pub(crate) fn render_impls(
|
||||
cx: &mut Context<'_>,
|
||||
cx: &Context<'_>,
|
||||
mut w: impl Write,
|
||||
impls: &[&Impl],
|
||||
containing_item: &clean::Item,
|
||||
toggle_open_by_default: bool,
|
||||
) {
|
||||
let tcx = cx.tcx();
|
||||
let mut rendered_impls = impls
|
||||
.iter()
|
||||
.map(|i| {
|
||||
let did = i.trait_did().unwrap();
|
||||
let provided_trait_methods = i.inner_impl().provided_trait_methods(tcx);
|
||||
let provided_trait_methods = i.inner_impl().provided_trait_methods(cx.tcx());
|
||||
let assoc_link = AssocItemLink::GotoSource(did.into(), &provided_trait_methods);
|
||||
let mut buffer = Buffer::new();
|
||||
render_impl(
|
||||
@ -906,7 +905,7 @@ fn assoc_method(
|
||||
d: &clean::FnDecl,
|
||||
link: AssocItemLink<'_>,
|
||||
parent: ItemType,
|
||||
cx: &mut Context<'_>,
|
||||
cx: &Context<'_>,
|
||||
render_mode: RenderMode,
|
||||
) {
|
||||
let tcx = cx.tcx();
|
||||
@ -1071,7 +1070,7 @@ fn render_assoc_item(
|
||||
item: &clean::Item,
|
||||
link: AssocItemLink<'_>,
|
||||
parent: ItemType,
|
||||
cx: &mut Context<'_>,
|
||||
cx: &Context<'_>,
|
||||
render_mode: RenderMode,
|
||||
) {
|
||||
match &item.kind {
|
||||
@ -1191,7 +1190,7 @@ fn write_impl_section_heading(w: &mut impl fmt::Write, title: &str, id: &str) {
|
||||
|
||||
pub(crate) fn render_all_impls(
|
||||
mut w: impl Write,
|
||||
cx: &mut Context<'_>,
|
||||
cx: &Context<'_>,
|
||||
containing_item: &clean::Item,
|
||||
concrete: &[&Impl],
|
||||
synthetic: &[&Impl],
|
||||
@ -1225,7 +1224,7 @@ pub(crate) fn render_all_impls(
|
||||
}
|
||||
|
||||
fn render_assoc_items<'a, 'cx: 'a>(
|
||||
cx: &'a mut Context<'cx>,
|
||||
cx: &'a Context<'cx>,
|
||||
containing_item: &'a clean::Item,
|
||||
it: DefId,
|
||||
what: AssocItemRender<'a>,
|
||||
@ -1240,15 +1239,14 @@ fn render_assoc_items<'a, 'cx: 'a>(
|
||||
|
||||
fn render_assoc_items_inner(
|
||||
mut w: &mut dyn fmt::Write,
|
||||
cx: &mut Context<'_>,
|
||||
cx: &Context<'_>,
|
||||
containing_item: &clean::Item,
|
||||
it: DefId,
|
||||
what: AssocItemRender<'_>,
|
||||
derefs: &mut DefIdSet,
|
||||
) {
|
||||
info!("Documenting associated items of {:?}", containing_item.name);
|
||||
let shared = Rc::clone(&cx.shared);
|
||||
let cache = &shared.cache;
|
||||
let cache = &cx.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() {
|
||||
@ -1276,7 +1274,7 @@ fn render_assoc_items_inner(
|
||||
);
|
||||
tmp_buf.write_str("</summary>");
|
||||
if let Some(def_id) = type_.def_id(cx.cache()) {
|
||||
cx.deref_id_map.insert(def_id, id);
|
||||
cx.deref_id_map.borrow_mut().insert(def_id, id);
|
||||
}
|
||||
(RenderMode::ForDeref { mut_: deref_mut_ }, derived_id, r#" class="impl-items""#)
|
||||
}
|
||||
@ -1340,7 +1338,7 @@ fn render_assoc_items_inner(
|
||||
|
||||
fn render_deref_methods(
|
||||
mut w: impl Write,
|
||||
cx: &mut Context<'_>,
|
||||
cx: &Context<'_>,
|
||||
impl_: &Impl,
|
||||
container_item: &clean::Item,
|
||||
deref_mut: bool,
|
||||
@ -1407,7 +1405,7 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) ->
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn notable_traits_button(ty: &clean::Type, cx: &mut Context<'_>) -> Option<String> {
|
||||
pub(crate) fn notable_traits_button(ty: &clean::Type, cx: &Context<'_>) -> Option<String> {
|
||||
let mut has_notable_trait = false;
|
||||
|
||||
if ty.is_unit() {
|
||||
@ -1450,7 +1448,7 @@ pub(crate) fn notable_traits_button(ty: &clean::Type, cx: &mut Context<'_>) -> O
|
||||
}
|
||||
|
||||
if has_notable_trait {
|
||||
cx.types_with_notable_traits.insert(ty.clone());
|
||||
cx.types_with_notable_traits.borrow_mut().insert(ty.clone());
|
||||
Some(format!(
|
||||
" <a href=\"#\" class=\"tooltip\" data-notable-ty=\"{ty}\">ⓘ</a>",
|
||||
ty = Escape(&format!("{:#}", ty.print(cx))),
|
||||
@ -1554,7 +1552,7 @@ struct ImplRenderingParameters {
|
||||
|
||||
fn render_impl(
|
||||
w: &mut Buffer,
|
||||
cx: &mut Context<'_>,
|
||||
cx: &Context<'_>,
|
||||
i: &Impl,
|
||||
parent: &clean::Item,
|
||||
link: AssocItemLink<'_>,
|
||||
@ -1563,8 +1561,7 @@ fn render_impl(
|
||||
aliases: &[String],
|
||||
rendering_params: ImplRenderingParameters,
|
||||
) {
|
||||
let shared = Rc::clone(&cx.shared);
|
||||
let cache = &shared.cache;
|
||||
let cache = &cx.shared.cache;
|
||||
let traits = &cache.traits;
|
||||
let trait_ = i.trait_did().map(|did| &traits[&did]);
|
||||
let mut close_tags = <Vec<&str>>::with_capacity(2);
|
||||
@ -1577,7 +1574,7 @@ fn render_impl(
|
||||
fn doc_impl_item(
|
||||
boring: &mut Buffer,
|
||||
interesting: &mut Buffer,
|
||||
cx: &mut Context<'_>,
|
||||
cx: &Context<'_>,
|
||||
item: &clean::Item,
|
||||
parent: &clean::Item,
|
||||
link: AssocItemLink<'_>,
|
||||
@ -1867,7 +1864,7 @@ fn render_impl(
|
||||
fn render_default_items(
|
||||
boring: &mut Buffer,
|
||||
interesting: &mut Buffer,
|
||||
cx: &mut Context<'_>,
|
||||
cx: &Context<'_>,
|
||||
t: &clean::Trait,
|
||||
i: &clean::Impl,
|
||||
parent: &clean::Item,
|
||||
@ -1907,6 +1904,7 @@ fn render_impl(
|
||||
}
|
||||
}
|
||||
|
||||
let trait_is_none = trait_.is_none();
|
||||
// If we've implemented a trait, then also emit documentation for all
|
||||
// default items which weren't overridden in the implementation block.
|
||||
// We don't emit documentation for default items if they appear in the
|
||||
@ -1952,7 +1950,7 @@ fn render_impl(
|
||||
}
|
||||
|
||||
if let Some(ref dox) = i.impl_item.opt_doc_value() {
|
||||
if trait_.is_none() && impl_.items.is_empty() {
|
||||
if trait_is_none && impl_.items.is_empty() {
|
||||
w.write_str(
|
||||
"<div class=\"item-info\">\
|
||||
<div class=\"stab empty-impl\">This impl block contains no items.</div>\
|
||||
@ -1965,7 +1963,7 @@ fn render_impl(
|
||||
Markdown {
|
||||
content: dox,
|
||||
links: &i.impl_item.links(cx),
|
||||
ids: &mut cx.id_map,
|
||||
ids: &mut cx.id_map.borrow_mut(),
|
||||
error_codes: cx.shared.codes,
|
||||
edition: cx.shared.edition(),
|
||||
playground: &cx.shared.playground,
|
||||
@ -2025,7 +2023,7 @@ fn render_rightside(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, render
|
||||
|
||||
pub(crate) fn render_impl_summary(
|
||||
w: &mut Buffer,
|
||||
cx: &mut Context<'_>,
|
||||
cx: &Context<'_>,
|
||||
i: &Impl,
|
||||
parent: &clean::Item,
|
||||
show_def_docs: bool,
|
||||
@ -2186,7 +2184,7 @@ fn extract_for_impl_name(item: &clean::Item, cx: &Context<'_>) -> Option<(String
|
||||
/// implementations that are on concrete or partially generic types, only keeping implementations
|
||||
/// of the form `impl<T> Trait for &T`.
|
||||
pub(crate) fn get_filtered_impls_for_reference<'a>(
|
||||
shared: &'a Rc<SharedContext<'_>>,
|
||||
shared: &'a SharedContext<'_>,
|
||||
it: &clean::Item,
|
||||
) -> (Vec<&'a Impl>, Vec<&'a Impl>, Vec<&'a Impl>) {
|
||||
let def_id = it.item_id.expect_def_id();
|
||||
@ -2423,14 +2421,14 @@ const MAX_FULL_EXAMPLES: usize = 5;
|
||||
const NUM_VISIBLE_LINES: usize = 10;
|
||||
|
||||
/// Generates the HTML for example call locations generated via the --scrape-examples flag.
|
||||
fn render_call_locations<W: fmt::Write>(mut w: W, cx: &mut Context<'_>, item: &clean::Item) {
|
||||
fn render_call_locations<W: fmt::Write>(mut w: W, cx: &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.derive("scraped-examples");
|
||||
let id = cx.derive_id("scraped-examples");
|
||||
write!(
|
||||
&mut w,
|
||||
"<div class=\"docblock scraped-example-list\">\
|
||||
|
@ -1,7 +1,5 @@
|
||||
use std::cell::{RefCell, RefMut};
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt;
|
||||
use std::rc::Rc;
|
||||
|
||||
use itertools::Itertools;
|
||||
use rinja::Template;
|
||||
@ -61,7 +59,7 @@ macro_rules! item_template {
|
||||
(
|
||||
$(#[$meta:meta])*
|
||||
struct $name:ident<'a, 'cx> {
|
||||
cx: RefCell<&'a mut Context<'cx>>,
|
||||
cx: &'a Context<'cx>,
|
||||
it: &'a clean::Item,
|
||||
$($field_name:ident: $field_ty:ty),*,
|
||||
},
|
||||
@ -70,14 +68,14 @@ macro_rules! item_template {
|
||||
#[derive(Template)]
|
||||
$(#[$meta])*
|
||||
struct $name<'a, 'cx> {
|
||||
cx: RefCell<&'a mut Context<'cx>>,
|
||||
cx: &'a Context<'cx>,
|
||||
it: &'a clean::Item,
|
||||
$($field_name: $field_ty),*
|
||||
}
|
||||
|
||||
impl<'a, 'cx: 'a> ItemTemplate<'a, 'cx> for $name<'a, 'cx> {
|
||||
fn item_and_mut_cx(&self) -> (&'a clean::Item, RefMut<'_, &'a mut Context<'cx>>) {
|
||||
(&self.it, self.cx.borrow_mut())
|
||||
fn item_and_cx(&self) -> (&'a clean::Item, &'a Context<'cx>) {
|
||||
(&self.it, &self.cx)
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,8 +93,8 @@ macro_rules! item_template_methods {
|
||||
(document $($rest:tt)*) => {
|
||||
fn document<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
|
||||
display_fn(move |f| {
|
||||
let (item, mut cx) = self.item_and_mut_cx();
|
||||
let v = document(*cx, item, None, HeadingOffset::H2);
|
||||
let (item, cx) = self.item_and_cx();
|
||||
let v = document(cx, item, None, HeadingOffset::H2);
|
||||
write!(f, "{v}")
|
||||
})
|
||||
}
|
||||
@ -105,9 +103,9 @@ macro_rules! item_template_methods {
|
||||
(document_type_layout $($rest:tt)*) => {
|
||||
fn document_type_layout<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
|
||||
display_fn(move |f| {
|
||||
let (item, cx) = self.item_and_mut_cx();
|
||||
let (item, cx) = self.item_and_cx();
|
||||
let def_id = item.item_id.expect_def_id();
|
||||
let v = document_type_layout(*cx, def_id);
|
||||
let v = document_type_layout(cx, def_id);
|
||||
write!(f, "{v}")
|
||||
})
|
||||
}
|
||||
@ -116,8 +114,8 @@ macro_rules! item_template_methods {
|
||||
(render_attributes_in_pre $($rest:tt)*) => {
|
||||
fn render_attributes_in_pre<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
|
||||
display_fn(move |f| {
|
||||
let (item, cx) = self.item_and_mut_cx();
|
||||
let v = render_attributes_in_pre(item, "", &cx);
|
||||
let (item, cx) = self.item_and_cx();
|
||||
let v = render_attributes_in_pre(item, "", cx);
|
||||
write!(f, "{v}")
|
||||
})
|
||||
}
|
||||
@ -126,9 +124,9 @@ macro_rules! item_template_methods {
|
||||
(render_assoc_items $($rest:tt)*) => {
|
||||
fn render_assoc_items<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
|
||||
display_fn(move |f| {
|
||||
let (item, mut cx) = self.item_and_mut_cx();
|
||||
let (item, cx) = self.item_and_cx();
|
||||
let def_id = item.item_id.expect_def_id();
|
||||
let v = render_assoc_items(*cx, item, def_id, AssocItemRender::All);
|
||||
let v = render_assoc_items(cx, item, def_id, AssocItemRender::All);
|
||||
write!(f, "{v}")
|
||||
})
|
||||
}
|
||||
@ -175,7 +173,7 @@ fn print_where_clause_and_check<'a, 'tcx: 'a>(
|
||||
len_before != buffer.len()
|
||||
}
|
||||
|
||||
pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buffer) {
|
||||
pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer) {
|
||||
debug_assert!(!item.is_stripped());
|
||||
let typ = match item.kind {
|
||||
clean::ModuleItem(_) => {
|
||||
@ -223,7 +221,7 @@ pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buf
|
||||
// this page, and this link will be auto-clicked. The `id` attribute is
|
||||
// used to find the link to auto-click.
|
||||
let src_href =
|
||||
if cx.include_sources && !item.is_primitive() { cx.src_href(item) } else { None };
|
||||
if cx.info.include_sources && !item.is_primitive() { cx.src_href(item) } else { None };
|
||||
|
||||
let path_components = if item.is_primitive() || item.is_keyword() {
|
||||
vec![]
|
||||
@ -277,13 +275,14 @@ pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buf
|
||||
}
|
||||
|
||||
// Render notable-traits.js used for all methods in this module.
|
||||
if !cx.types_with_notable_traits.is_empty() {
|
||||
let mut types_with_notable_traits = cx.types_with_notable_traits.borrow_mut();
|
||||
if !types_with_notable_traits.is_empty() {
|
||||
write!(
|
||||
buf,
|
||||
r#"<script type="text/json" id="notable-traits-data">{}</script>"#,
|
||||
notable_traits_json(cx.types_with_notable_traits.iter(), cx)
|
||||
notable_traits_json(types_with_notable_traits.iter(), cx)
|
||||
);
|
||||
cx.types_with_notable_traits.clear();
|
||||
types_with_notable_traits.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@ -308,10 +307,10 @@ fn toggle_close(mut w: impl fmt::Write) {
|
||||
}
|
||||
|
||||
trait ItemTemplate<'a, 'cx: 'a>: rinja::Template + fmt::Display {
|
||||
fn item_and_mut_cx(&self) -> (&'a clean::Item, RefMut<'_, &'a mut Context<'cx>>);
|
||||
fn item_and_cx(&self) -> (&'a clean::Item, &'a Context<'cx>);
|
||||
}
|
||||
|
||||
fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: &[clean::Item]) {
|
||||
fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) {
|
||||
write!(w, "{}", document(cx, item, None, HeadingOffset::H2));
|
||||
|
||||
let mut not_stripped_items =
|
||||
@ -594,7 +593,7 @@ fn extra_info_tags<'a, 'tcx: 'a>(
|
||||
})
|
||||
}
|
||||
|
||||
fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &clean::Function) {
|
||||
fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::Function) {
|
||||
let tcx = cx.tcx();
|
||||
let header = it.fn_header(tcx).expect("printing a function which isn't a function");
|
||||
debug!(
|
||||
@ -649,7 +648,7 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle
|
||||
write!(w, "{}", document(cx, it, None, HeadingOffset::H2));
|
||||
}
|
||||
|
||||
fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Trait) {
|
||||
fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Trait) {
|
||||
let tcx = cx.tcx();
|
||||
let bounds = bounds(&t.bounds, false, cx);
|
||||
let required_types = t.items.iter().filter(|m| m.is_ty_associated_type()).collect::<Vec<_>>();
|
||||
@ -801,7 +800,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
|
||||
// Trait documentation
|
||||
write!(w, "{}", document(cx, it, None, HeadingOffset::H2));
|
||||
|
||||
fn trait_item(w: &mut Buffer, cx: &mut Context<'_>, m: &clean::Item, t: &clean::Item) {
|
||||
fn trait_item(w: &mut Buffer, cx: &Context<'_>, m: &clean::Item, t: &clean::Item) {
|
||||
let name = m.name.unwrap();
|
||||
info!("Documenting {name} on {ty_name:?}", ty_name = t.name);
|
||||
let item_type = m.type_();
|
||||
@ -929,8 +928,6 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
|
||||
// If there are methods directly on this trait object, render them here.
|
||||
write!(w, "{}", render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All));
|
||||
|
||||
let cloned_shared = Rc::clone(&cx.shared);
|
||||
let cache = &cloned_shared.cache;
|
||||
let mut extern_crates = FxIndexSet::default();
|
||||
|
||||
if !t.is_dyn_compatible(cx.tcx()) {
|
||||
@ -950,12 +947,13 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(implementors) = cache.implementors.get(&it.item_id.expect_def_id()) {
|
||||
if let Some(implementors) = cx.shared.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<Symbol, (DefId, bool)> = FxHashMap::default();
|
||||
for implementor in implementors {
|
||||
if let Some(did) = implementor.inner_impl().for_.without_borrowed_ref().def_id(cache)
|
||||
if let Some(did) =
|
||||
implementor.inner_impl().for_.without_borrowed_ref().def_id(&cx.shared.cache)
|
||||
&& !did.is_local()
|
||||
{
|
||||
extern_crates.insert(did.krate);
|
||||
@ -1036,7 +1034,10 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
|
||||
it,
|
||||
w,
|
||||
&implementor_dups,
|
||||
&collect_paths_for_type(implementor.inner_impl().for_.clone(), cache),
|
||||
&collect_paths_for_type(
|
||||
implementor.inner_impl().for_.clone(),
|
||||
&cx.shared.cache,
|
||||
),
|
||||
);
|
||||
}
|
||||
w.write_str("</div>");
|
||||
@ -1139,8 +1140,8 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
|
||||
.chain(std::iter::once("trait.impl"))
|
||||
.collect();
|
||||
if let Some(did) = it.item_id.as_def_id()
|
||||
&& let get_extern = { || cache.external_paths.get(&did).map(|s| &s.0) }
|
||||
&& let Some(fqp) = cache.exact_paths.get(&did).or_else(get_extern)
|
||||
&& let get_extern = { || cx.shared.cache.external_paths.get(&did).map(|s| &s.0) }
|
||||
&& let Some(fqp) = cx.shared.cache.exact_paths.get(&did).or_else(get_extern)
|
||||
{
|
||||
js_src_path.extend(fqp[..fqp.len() - 1].iter().copied());
|
||||
js_src_path.push_fmt(format_args!("{}.{}.js", it.type_(), fqp.last().unwrap()));
|
||||
@ -1164,7 +1165,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
|
||||
|
||||
fn item_trait_alias(
|
||||
w: &mut impl fmt::Write,
|
||||
cx: &mut Context<'_>,
|
||||
cx: &Context<'_>,
|
||||
it: &clean::Item,
|
||||
t: &clean::TraitAlias,
|
||||
) {
|
||||
@ -1190,7 +1191,7 @@ fn item_trait_alias(
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::TypeAlias) {
|
||||
fn item_type_alias(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::TypeAlias) {
|
||||
wrap_item(w, |w| {
|
||||
write!(
|
||||
w,
|
||||
@ -1355,8 +1356,7 @@ fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &c
|
||||
//
|
||||
// [JSONP]: https://en.wikipedia.org/wiki/JSONP
|
||||
// [^115718]: https://github.com/rust-lang/rust/issues/115718
|
||||
let cloned_shared = Rc::clone(&cx.shared);
|
||||
let cache = &cloned_shared.cache;
|
||||
let cache = &cx.shared.cache;
|
||||
if let Some(target_did) = t.type_.def_id(cache) &&
|
||||
let get_extern = { || cache.external_paths.get(&target_did) } &&
|
||||
let Some(&(ref target_fqp, target_type)) = cache.paths.get(&target_did).or_else(get_extern) &&
|
||||
@ -1380,11 +1380,11 @@ fn item_type_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &c
|
||||
}
|
||||
}
|
||||
|
||||
fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Union) {
|
||||
fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Union) {
|
||||
item_template!(
|
||||
#[template(path = "item_union.html")]
|
||||
struct ItemUnion<'a, 'cx> {
|
||||
cx: RefCell<&'a mut Context<'cx>>,
|
||||
cx: &'a Context<'cx>,
|
||||
it: &'a clean::Item,
|
||||
s: &'a clean::Union,
|
||||
},
|
||||
@ -1394,8 +1394,7 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean:
|
||||
impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> {
|
||||
fn render_union<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
|
||||
display_fn(move |f| {
|
||||
let cx = self.cx.borrow_mut();
|
||||
let v = render_union(self.it, Some(&self.s.generics), &self.s.fields, *cx);
|
||||
let v = render_union(self.it, Some(&self.s.generics), &self.s.fields, self.cx);
|
||||
write!(f, "{v}")
|
||||
})
|
||||
}
|
||||
@ -1405,15 +1404,13 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean:
|
||||
field: &'a clean::Item,
|
||||
) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
|
||||
display_fn(move |f| {
|
||||
let mut cx = self.cx.borrow_mut();
|
||||
let v = document(*cx, field, Some(self.it), HeadingOffset::H3);
|
||||
let v = document(self.cx, field, Some(self.it), HeadingOffset::H3);
|
||||
write!(f, "{v}")
|
||||
})
|
||||
}
|
||||
|
||||
fn stability_field(&self, field: &clean::Item) -> Option<String> {
|
||||
let cx = self.cx.borrow();
|
||||
field.stability_class(cx.tcx())
|
||||
field.stability_class(self.cx.tcx())
|
||||
}
|
||||
|
||||
fn print_ty<'b>(
|
||||
@ -1421,8 +1418,7 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean:
|
||||
ty: &'a clean::Type,
|
||||
) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
|
||||
display_fn(move |f| {
|
||||
let cx = self.cx.borrow();
|
||||
let v = ty.print(*cx);
|
||||
let v = ty.print(&self.cx);
|
||||
write!(f, "{v}")
|
||||
})
|
||||
}
|
||||
@ -1441,7 +1437,7 @@ fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean:
|
||||
}
|
||||
}
|
||||
|
||||
ItemUnion { cx: RefCell::new(cx), it, s }.render_into(w).unwrap();
|
||||
ItemUnion { cx, it, s }.render_into(w).unwrap();
|
||||
}
|
||||
|
||||
fn print_tuple_struct_fields<'a, 'cx: 'a>(
|
||||
@ -1471,7 +1467,7 @@ fn print_tuple_struct_fields<'a, 'cx: 'a>(
|
||||
})
|
||||
}
|
||||
|
||||
fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::Enum) {
|
||||
fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum) {
|
||||
let count_variants = e.variants().count();
|
||||
wrap_item(w, |w| {
|
||||
render_attributes_in_code(w, it, cx);
|
||||
@ -1532,7 +1528,7 @@ fn should_show_enum_discriminant(
|
||||
|
||||
fn display_c_like_variant(
|
||||
w: &mut Buffer,
|
||||
cx: &mut Context<'_>,
|
||||
cx: &Context<'_>,
|
||||
item: &clean::Item,
|
||||
variant: &clean::Variant,
|
||||
index: VariantIdx,
|
||||
@ -1557,7 +1553,7 @@ fn display_c_like_variant(
|
||||
|
||||
fn render_enum_fields(
|
||||
mut w: &mut Buffer,
|
||||
cx: &mut Context<'_>,
|
||||
cx: &Context<'_>,
|
||||
g: Option<&clean::Generics>,
|
||||
variants: &IndexVec<VariantIdx, clean::Item>,
|
||||
count_variants: usize,
|
||||
@ -1621,7 +1617,7 @@ fn render_enum_fields(
|
||||
|
||||
fn item_variants(
|
||||
w: &mut Buffer,
|
||||
cx: &mut Context<'_>,
|
||||
cx: &Context<'_>,
|
||||
it: &clean::Item,
|
||||
variants: &IndexVec<VariantIdx, clean::Item>,
|
||||
enum_def_id: DefId,
|
||||
@ -1743,7 +1739,7 @@ fn item_variants(
|
||||
write!(w, "</div>");
|
||||
}
|
||||
|
||||
fn item_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Macro) {
|
||||
fn item_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Macro) {
|
||||
wrap_item(w, |w| {
|
||||
// FIXME: Also print `#[doc(hidden)]` for `macro_rules!` if it `is_doc_hidden`.
|
||||
if !t.macro_rules {
|
||||
@ -1756,7 +1752,7 @@ fn item_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
|
||||
|
||||
fn item_proc_macro(
|
||||
w: &mut impl fmt::Write,
|
||||
cx: &mut Context<'_>,
|
||||
cx: &Context<'_>,
|
||||
it: &clean::Item,
|
||||
m: &clean::ProcMacro,
|
||||
) {
|
||||
@ -1790,7 +1786,7 @@ fn item_proc_macro(
|
||||
write!(w, "{}", document(cx, it, None, HeadingOffset::H2)).unwrap();
|
||||
}
|
||||
|
||||
fn item_primitive(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Item) {
|
||||
fn item_primitive(w: &mut impl fmt::Write, cx: &Context<'_>, it: &clean::Item) {
|
||||
let def_id = it.item_id.expect_def_id();
|
||||
write!(w, "{}", document(cx, it, None, HeadingOffset::H2)).unwrap();
|
||||
if it.name.map(|n| n.as_str() != "reference").unwrap_or(false) {
|
||||
@ -1798,8 +1794,7 @@ fn item_primitive(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Ite
|
||||
} else {
|
||||
// We handle the "reference" primitive type on its own because we only want to list
|
||||
// implementations on generic types.
|
||||
let shared = Rc::clone(&cx.shared);
|
||||
let (concrete, synthetic, blanket_impl) = get_filtered_impls_for_reference(&shared, it);
|
||||
let (concrete, synthetic, blanket_impl) = get_filtered_impls_for_reference(&cx.shared, it);
|
||||
|
||||
render_all_impls(w, cx, it, &concrete, &synthetic, &blanket_impl);
|
||||
}
|
||||
@ -1807,7 +1802,7 @@ fn item_primitive(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Ite
|
||||
|
||||
fn item_constant(
|
||||
w: &mut Buffer,
|
||||
cx: &mut Context<'_>,
|
||||
cx: &Context<'_>,
|
||||
it: &clean::Item,
|
||||
generics: &clean::Generics,
|
||||
ty: &clean::Type,
|
||||
@ -1862,7 +1857,7 @@ fn item_constant(
|
||||
write!(w, "{}", document(cx, it, None, HeadingOffset::H2))
|
||||
}
|
||||
|
||||
fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Struct) {
|
||||
fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Struct) {
|
||||
wrap_item(w, |w| {
|
||||
render_attributes_in_code(w, it, cx);
|
||||
render_struct(w, it, Some(&s.generics), s.ctor_kind, &s.fields, "", true, cx);
|
||||
@ -1879,7 +1874,7 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean
|
||||
|
||||
fn item_fields(
|
||||
w: &mut Buffer,
|
||||
cx: &mut Context<'_>,
|
||||
cx: &Context<'_>,
|
||||
it: &clean::Item,
|
||||
fields: &[clean::Item],
|
||||
ctor_kind: Option<CtorKind>,
|
||||
@ -1920,7 +1915,7 @@ fn item_fields(
|
||||
|
||||
fn item_static(
|
||||
w: &mut impl fmt::Write,
|
||||
cx: &mut Context<'_>,
|
||||
cx: &Context<'_>,
|
||||
it: &clean::Item,
|
||||
s: &clean::Static,
|
||||
safety: Option<hir::Safety>,
|
||||
@ -1944,7 +1939,7 @@ fn item_static(
|
||||
write!(w, "{}", document(cx, it, None, HeadingOffset::H2)).unwrap();
|
||||
}
|
||||
|
||||
fn item_foreign_type(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Item) {
|
||||
fn item_foreign_type(w: &mut impl fmt::Write, cx: &Context<'_>, it: &clean::Item) {
|
||||
wrap_item(w, |buffer| {
|
||||
buffer.write_str("extern {\n").unwrap();
|
||||
render_attributes_in_code(buffer, it, cx);
|
||||
@ -1962,7 +1957,7 @@ fn item_foreign_type(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn item_keyword(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
|
||||
fn item_keyword(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
|
||||
write!(w, "{}", document(cx, it, None, HeadingOffset::H2))
|
||||
}
|
||||
|
||||
@ -2134,7 +2129,7 @@ impl Ord for ImplString {
|
||||
}
|
||||
|
||||
fn render_implementor(
|
||||
cx: &mut Context<'_>,
|
||||
cx: &Context<'_>,
|
||||
implementor: &Impl,
|
||||
trait_: &clean::Item,
|
||||
w: &mut Buffer,
|
||||
|
@ -1,10 +1,9 @@
|
||||
use std::borrow::Cow;
|
||||
use std::rc::Rc;
|
||||
|
||||
use rinja::Template;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_hir::def::CtorKind;
|
||||
use rustc_hir::def_id::DefIdSet;
|
||||
use rustc_hir::def_id::{DefIdMap, DefIdSet};
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use tracing::debug;
|
||||
|
||||
@ -119,17 +118,18 @@ pub(crate) mod filters {
|
||||
pub(super) fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) {
|
||||
let mut ids = IdMap::new();
|
||||
let mut blocks: Vec<LinkBlock<'_>> = docblock_toc(cx, it, &mut ids).into_iter().collect();
|
||||
let deref_id_map = cx.deref_id_map.borrow();
|
||||
match it.kind {
|
||||
clean::StructItem(ref s) => sidebar_struct(cx, it, s, &mut blocks),
|
||||
clean::TraitItem(ref t) => sidebar_trait(cx, it, t, &mut blocks),
|
||||
clean::PrimitiveItem(_) => sidebar_primitive(cx, it, &mut blocks),
|
||||
clean::UnionItem(ref u) => sidebar_union(cx, it, u, &mut blocks),
|
||||
clean::EnumItem(ref e) => sidebar_enum(cx, it, e, &mut blocks),
|
||||
clean::TypeAliasItem(ref t) => sidebar_type_alias(cx, it, t, &mut blocks),
|
||||
clean::StructItem(ref s) => sidebar_struct(cx, it, s, &mut blocks, &deref_id_map),
|
||||
clean::TraitItem(ref t) => sidebar_trait(cx, it, t, &mut blocks, &deref_id_map),
|
||||
clean::PrimitiveItem(_) => sidebar_primitive(cx, it, &mut blocks, &deref_id_map),
|
||||
clean::UnionItem(ref u) => sidebar_union(cx, it, u, &mut blocks, &deref_id_map),
|
||||
clean::EnumItem(ref e) => sidebar_enum(cx, it, e, &mut blocks, &deref_id_map),
|
||||
clean::TypeAliasItem(ref t) => sidebar_type_alias(cx, it, t, &mut blocks, &deref_id_map),
|
||||
clean::ModuleItem(ref m) => {
|
||||
blocks.push(sidebar_module(&m.items, &mut ids, ModuleLike::from(it)))
|
||||
}
|
||||
clean::ForeignTypeItem => sidebar_foreign_type(cx, it, &mut blocks),
|
||||
clean::ForeignTypeItem => sidebar_foreign_type(cx, it, &mut blocks, &deref_id_map),
|
||||
_ => {}
|
||||
}
|
||||
// The sidebar is designed to display sibling functions, modules and
|
||||
@ -245,6 +245,7 @@ fn sidebar_struct<'a>(
|
||||
it: &'a clean::Item,
|
||||
s: &'a clean::Struct,
|
||||
items: &mut Vec<LinkBlock<'a>>,
|
||||
deref_id_map: &'a DefIdMap<String>,
|
||||
) {
|
||||
let fields = get_struct_fields_name(&s.fields);
|
||||
let field_name = match s.ctor_kind {
|
||||
@ -255,7 +256,7 @@ fn sidebar_struct<'a>(
|
||||
if let Some(name) = field_name {
|
||||
items.push(LinkBlock::new(Link::new("fields", name), "structfield", fields));
|
||||
}
|
||||
sidebar_assoc_items(cx, it, items);
|
||||
sidebar_assoc_items(cx, it, items, deref_id_map);
|
||||
}
|
||||
|
||||
fn sidebar_trait<'a>(
|
||||
@ -263,6 +264,7 @@ fn sidebar_trait<'a>(
|
||||
it: &'a clean::Item,
|
||||
t: &'a clean::Trait,
|
||||
blocks: &mut Vec<LinkBlock<'a>>,
|
||||
deref_id_map: &'a DefIdMap<String>,
|
||||
) {
|
||||
fn filter_items<'a>(
|
||||
items: &'a [clean::Item],
|
||||
@ -313,7 +315,7 @@ fn sidebar_trait<'a>(
|
||||
.into_iter()
|
||||
.map(|(id, title, items)| LinkBlock::new(Link::new(id, title), "", items)),
|
||||
);
|
||||
sidebar_assoc_items(cx, it, blocks);
|
||||
sidebar_assoc_items(cx, it, blocks, deref_id_map);
|
||||
|
||||
if !t.is_dyn_compatible(cx.tcx()) {
|
||||
blocks.push(LinkBlock::forced(
|
||||
@ -331,13 +333,17 @@ fn sidebar_trait<'a>(
|
||||
}
|
||||
}
|
||||
|
||||
fn sidebar_primitive<'a>(cx: &'a Context<'_>, it: &'a clean::Item, items: &mut Vec<LinkBlock<'a>>) {
|
||||
fn sidebar_primitive<'a>(
|
||||
cx: &'a Context<'_>,
|
||||
it: &'a clean::Item,
|
||||
items: &mut Vec<LinkBlock<'a>>,
|
||||
deref_id_map: &'a DefIdMap<String>,
|
||||
) {
|
||||
if it.name.map(|n| n.as_str() != "reference").unwrap_or(false) {
|
||||
sidebar_assoc_items(cx, it, items);
|
||||
sidebar_assoc_items(cx, it, items, deref_id_map);
|
||||
} else {
|
||||
let shared = Rc::clone(&cx.shared);
|
||||
let (concrete, synthetic, blanket_impl) =
|
||||
super::get_filtered_impls_for_reference(&shared, it);
|
||||
super::get_filtered_impls_for_reference(&cx.shared, it);
|
||||
|
||||
sidebar_render_assoc_items(cx, &mut IdMap::new(), concrete, synthetic, blanket_impl, items);
|
||||
}
|
||||
@ -348,6 +354,7 @@ fn sidebar_type_alias<'a>(
|
||||
it: &'a clean::Item,
|
||||
t: &'a clean::TypeAlias,
|
||||
items: &mut Vec<LinkBlock<'a>>,
|
||||
deref_id_map: &'a DefIdMap<String>,
|
||||
) {
|
||||
if let Some(inner_type) = &t.inner_type {
|
||||
items.push(LinkBlock::forced(Link::new("aliased-type", "Aliased type"), "type"));
|
||||
@ -370,7 +377,7 @@ fn sidebar_type_alias<'a>(
|
||||
}
|
||||
}
|
||||
}
|
||||
sidebar_assoc_items(cx, it, items);
|
||||
sidebar_assoc_items(cx, it, items, deref_id_map);
|
||||
}
|
||||
|
||||
fn sidebar_union<'a>(
|
||||
@ -378,10 +385,11 @@ fn sidebar_union<'a>(
|
||||
it: &'a clean::Item,
|
||||
u: &'a clean::Union,
|
||||
items: &mut Vec<LinkBlock<'a>>,
|
||||
deref_id_map: &'a DefIdMap<String>,
|
||||
) {
|
||||
let fields = get_struct_fields_name(&u.fields);
|
||||
items.push(LinkBlock::new(Link::new("fields", "Fields"), "structfield", fields));
|
||||
sidebar_assoc_items(cx, it, items);
|
||||
sidebar_assoc_items(cx, it, items, deref_id_map);
|
||||
}
|
||||
|
||||
/// Adds trait implementations into the blocks of links
|
||||
@ -389,6 +397,7 @@ fn sidebar_assoc_items<'a>(
|
||||
cx: &'a Context<'_>,
|
||||
it: &'a clean::Item,
|
||||
links: &mut Vec<LinkBlock<'a>>,
|
||||
deref_id_map: &'a DefIdMap<String>,
|
||||
) {
|
||||
let did = it.item_id.expect_def_id();
|
||||
let cache = cx.cache();
|
||||
@ -433,7 +442,15 @@ fn sidebar_assoc_items<'a>(
|
||||
{
|
||||
let mut derefs = DefIdSet::default();
|
||||
derefs.insert(did);
|
||||
sidebar_deref_methods(cx, &mut blocks, impl_, v, &mut derefs, &mut used_links);
|
||||
sidebar_deref_methods(
|
||||
cx,
|
||||
&mut blocks,
|
||||
impl_,
|
||||
v,
|
||||
&mut derefs,
|
||||
&mut used_links,
|
||||
deref_id_map,
|
||||
);
|
||||
}
|
||||
|
||||
let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) =
|
||||
@ -462,6 +479,7 @@ fn sidebar_deref_methods<'a>(
|
||||
v: &[Impl],
|
||||
derefs: &mut DefIdSet,
|
||||
used_links: &mut FxHashSet<String>,
|
||||
deref_id_map: &'a DefIdMap<String>,
|
||||
) {
|
||||
let c = cx.cache();
|
||||
|
||||
@ -501,7 +519,7 @@ fn sidebar_deref_methods<'a>(
|
||||
if !ret.is_empty() {
|
||||
let id = if let Some(target_def_id) = real_target.def_id(c) {
|
||||
Cow::Borrowed(
|
||||
cx.deref_id_map
|
||||
deref_id_map
|
||||
.get(&target_def_id)
|
||||
.expect("Deref section without derived id")
|
||||
.as_str(),
|
||||
@ -531,7 +549,15 @@ fn sidebar_deref_methods<'a>(
|
||||
.unwrap_or(false)
|
||||
})
|
||||
{
|
||||
sidebar_deref_methods(cx, out, target_deref_impl, target_impls, derefs, used_links);
|
||||
sidebar_deref_methods(
|
||||
cx,
|
||||
out,
|
||||
target_deref_impl,
|
||||
target_impls,
|
||||
derefs,
|
||||
used_links,
|
||||
deref_id_map,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -541,6 +567,7 @@ fn sidebar_enum<'a>(
|
||||
it: &'a clean::Item,
|
||||
e: &'a clean::Enum,
|
||||
items: &mut Vec<LinkBlock<'a>>,
|
||||
deref_id_map: &'a DefIdMap<String>,
|
||||
) {
|
||||
let mut variants = e
|
||||
.variants()
|
||||
@ -550,7 +577,7 @@ fn sidebar_enum<'a>(
|
||||
variants.sort_unstable();
|
||||
|
||||
items.push(LinkBlock::new(Link::new("variants", "Variants"), "variant", variants));
|
||||
sidebar_assoc_items(cx, it, items);
|
||||
sidebar_assoc_items(cx, it, items, deref_id_map);
|
||||
}
|
||||
|
||||
pub(crate) fn sidebar_module_like(
|
||||
@ -607,8 +634,9 @@ fn sidebar_foreign_type<'a>(
|
||||
cx: &'a Context<'_>,
|
||||
it: &'a clean::Item,
|
||||
items: &mut Vec<LinkBlock<'a>>,
|
||||
deref_id_map: &'a DefIdMap<String>,
|
||||
) {
|
||||
sidebar_assoc_items(cx, it, items);
|
||||
sidebar_assoc_items(cx, it, items, deref_id_map);
|
||||
}
|
||||
|
||||
/// Renders the trait implementations for this type
|
||||
|
@ -43,7 +43,6 @@ use crate::config::{EmitType, PathToParts, RenderOptions, ShouldMerge};
|
||||
use crate::docfs::PathError;
|
||||
use crate::error::Error;
|
||||
use crate::formats::Impl;
|
||||
use crate::formats::cache::Cache;
|
||||
use crate::formats::item_type::ItemType;
|
||||
use crate::html::format::Buffer;
|
||||
use crate::html::layout;
|
||||
@ -62,13 +61,12 @@ pub(crate) fn write_shared(
|
||||
tcx: TyCtxt<'_>,
|
||||
) -> Result<(), Error> {
|
||||
// NOTE(EtomicBomb): I don't think we need sync here because no read-after-write?
|
||||
Rc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(true);
|
||||
cx.shared.fs.set_sync_only(true);
|
||||
let lock_file = cx.dst.join(".lock");
|
||||
// Write shared runs within a flock; disable thread dispatching of IO temporarily.
|
||||
let _lock = try_err!(flock::Lock::new(&lock_file, true, true, true), &lock_file);
|
||||
|
||||
let SerializedSearchIndex { index, desc } =
|
||||
build_index(krate, &mut Rc::get_mut(&mut cx.shared).unwrap().cache, tcx);
|
||||
let SerializedSearchIndex { index, desc } = build_index(krate, &mut cx.shared.cache, tcx);
|
||||
write_search_desc(cx, krate, &desc)?; // does not need to be merged
|
||||
|
||||
let crate_name = krate.name(cx.tcx());
|
||||
@ -104,7 +102,7 @@ pub(crate) fn write_shared(
|
||||
&cx.shared.style_files,
|
||||
cx.shared.layout.css_file_extension.as_deref(),
|
||||
&cx.shared.resource_suffix,
|
||||
cx.include_sources,
|
||||
cx.info.include_sources,
|
||||
)?;
|
||||
match &opt.index_page {
|
||||
Some(index_page) if opt.enable_index_page => {
|
||||
@ -128,7 +126,7 @@ pub(crate) fn write_shared(
|
||||
}
|
||||
}
|
||||
|
||||
Rc::get_mut(&mut cx.shared).unwrap().fs.set_sync_only(false);
|
||||
cx.shared.fs.set_sync_only(false);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -597,13 +595,11 @@ impl TypeAliasPart {
|
||||
krate: &Crate,
|
||||
crate_name_json: &OrderedJson,
|
||||
) -> Result<PartsAndLocations<Self>, Error> {
|
||||
let cache = &Rc::clone(&cx.shared).cache;
|
||||
let mut path_parts = PartsAndLocations::default();
|
||||
|
||||
let mut type_impl_collector = TypeImplCollector {
|
||||
aliased_types: IndexMap::default(),
|
||||
visited_aliases: FxHashSet::default(),
|
||||
cache,
|
||||
cx,
|
||||
};
|
||||
DocVisitor::visit_crate(&mut type_impl_collector, krate);
|
||||
@ -625,14 +621,14 @@ impl TypeAliasPart {
|
||||
// each type alias, and if it gives a different result, split the impl
|
||||
for &(type_alias_fqp, type_alias_item) in type_aliases {
|
||||
let mut buf = Buffer::html();
|
||||
cx.id_map = Default::default();
|
||||
cx.deref_id_map = Default::default();
|
||||
cx.id_map.borrow_mut().clear();
|
||||
cx.deref_id_map.borrow_mut().clear();
|
||||
let target_did = impl_
|
||||
.inner_impl()
|
||||
.trait_
|
||||
.as_ref()
|
||||
.map(|trait_| trait_.def_id())
|
||||
.or_else(|| impl_.inner_impl().for_.def_id(cache));
|
||||
.or_else(|| impl_.inner_impl().for_.def_id(&cx.shared.cache));
|
||||
let provided_methods;
|
||||
let assoc_link = if let Some(target_did) = target_did {
|
||||
provided_methods = impl_.inner_impl().provided_trait_methods(cx.tcx());
|
||||
@ -720,7 +716,7 @@ impl TraitAliasPart {
|
||||
}
|
||||
|
||||
fn get(
|
||||
cx: &mut Context<'_>,
|
||||
cx: &Context<'_>,
|
||||
crate_name_json: &OrderedJson,
|
||||
) -> Result<PartsAndLocations<Self>, Error> {
|
||||
let cache = &cx.shared.cache;
|
||||
@ -828,8 +824,7 @@ struct TypeImplCollector<'cx, 'cache, 'item> {
|
||||
/// Map from DefId-of-aliased-type to its data.
|
||||
aliased_types: IndexMap<DefId, AliasedType<'cache, 'item>>,
|
||||
visited_aliases: FxHashSet<DefId>,
|
||||
cache: &'cache Cache,
|
||||
cx: &'cache mut Context<'cx>,
|
||||
cx: &'cache Context<'cx>,
|
||||
}
|
||||
|
||||
/// Data for an aliased type.
|
||||
@ -868,7 +863,7 @@ struct AliasedTypeImpl<'cache, 'item> {
|
||||
impl<'item> DocVisitor<'item> for TypeImplCollector<'_, '_, 'item> {
|
||||
fn visit_item(&mut self, it: &'item Item) {
|
||||
self.visit_item_recur(it);
|
||||
let cache = self.cache;
|
||||
let cache = &self.cx.shared.cache;
|
||||
let ItemKind::TypeAliasItem(ref t) = it.kind else { return };
|
||||
let Some(self_did) = it.item_id.as_def_id() else { return };
|
||||
if !self.visited_aliases.insert(self_did) {
|
||||
|
@ -2,7 +2,6 @@ use std::cell::RefCell;
|
||||
use std::ffi::OsStr;
|
||||
use std::ops::RangeInclusive;
|
||||
use std::path::{Component, Path, PathBuf};
|
||||
use std::rc::Rc;
|
||||
use std::{fmt, fs};
|
||||
|
||||
use rinja::Template;
|
||||
@ -124,7 +123,7 @@ struct SourceCollector<'a, 'tcx> {
|
||||
|
||||
impl DocVisitor<'_> for SourceCollector<'_, '_> {
|
||||
fn visit_item(&mut self, item: &clean::Item) {
|
||||
if !self.cx.include_sources {
|
||||
if !self.cx.info.include_sources {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -146,7 +145,7 @@ impl DocVisitor<'_> for SourceCollector<'_, '_> {
|
||||
// something like that), so just don't include sources for the
|
||||
// entire crate. The other option is maintaining this mapping on a
|
||||
// per-file basis, but that's probably not worth it...
|
||||
self.cx.include_sources = match self.emit_source(&filename, file_span) {
|
||||
self.cx.info.include_sources = match self.emit_source(&filename, file_span) {
|
||||
Ok(()) => true,
|
||||
Err(e) => {
|
||||
self.cx.shared.tcx.dcx().span_err(
|
||||
@ -197,7 +196,7 @@ impl SourceCollector<'_, '_> {
|
||||
// Remove the utf-8 BOM if any
|
||||
let contents = contents.strip_prefix('\u{feff}').unwrap_or(&contents);
|
||||
|
||||
let shared = Rc::clone(&self.cx.shared);
|
||||
let shared = &self.cx.shared;
|
||||
// Create the intermediate directories
|
||||
let cur = RefCell::new(PathBuf::new());
|
||||
let root_path = RefCell::new(PathBuf::new());
|
||||
@ -250,12 +249,11 @@ impl SourceCollector<'_, '_> {
|
||||
&page,
|
||||
"",
|
||||
|buf: &mut _| {
|
||||
let cx = &mut self.cx;
|
||||
print_src(
|
||||
buf,
|
||||
contents,
|
||||
file_span,
|
||||
cx,
|
||||
self.cx,
|
||||
&root_path,
|
||||
highlight::DecorationInfo::default(),
|
||||
SourceContext::Standalone { file_path },
|
||||
|
@ -137,6 +137,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
|
||||
}
|
||||
|
||||
const RUN_ON_MODULE: bool = false;
|
||||
type ModuleData = ();
|
||||
|
||||
fn init(
|
||||
krate: clean::Crate,
|
||||
@ -161,8 +162,12 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
|
||||
))
|
||||
}
|
||||
|
||||
fn make_child_renderer(&self) -> Self {
|
||||
self.clone()
|
||||
fn save_module_data(&mut self) -> Self::ModuleData {
|
||||
unreachable!("RUN_ON_MODULE = false should never call save_module_data")
|
||||
}
|
||||
|
||||
fn set_back_info(&mut self, _info: Self::ModuleData) {
|
||||
unreachable!("RUN_ON_MODULE = false should never call set_back_info")
|
||||
}
|
||||
|
||||
/// Inserts an item into the index. This should be used rather than directly calling insert on
|
||||
|
Loading…
Reference in New Issue
Block a user