Don't unnecessarily clone some fields in Context
There was no need to clone `id_map` because it was reset before each item was rendered. `deref_id_map` was not reset, but it was keyed by `DefId` and thus was unlikely to have collisions (at least for now). Now we just clone the fields that need to be cloned, and instead create fresh versions of the others.
This commit is contained in:
parent
ff39c46959
commit
c09d9d34f0
@ -9,7 +9,7 @@
|
||||
/// Allows for different backends to rustdoc to be used with the `run_format()` function. Each
|
||||
/// backend renderer has hooks for initialization, documenting an item, entering and exiting a
|
||||
/// module, and cleanup/finalizing output.
|
||||
crate trait FormatRenderer<'tcx>: Clone {
|
||||
crate trait FormatRenderer<'tcx>: Sized {
|
||||
/// Gives a description of the renderer. Used for performance profiling.
|
||||
fn descr() -> &'static str;
|
||||
|
||||
@ -23,6 +23,9 @@ fn init(
|
||||
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;
|
||||
|
||||
/// Renders a single non-module item. This means no recursive sub-item rendering is required.
|
||||
fn item(&mut self, item: clean::Item) -> Result<(), Error>;
|
||||
|
||||
@ -67,7 +70,7 @@ fn after_krate(
|
||||
item.name = Some(krate.name);
|
||||
|
||||
// Render the crate documentation
|
||||
let mut work = vec![(format_renderer.clone(), item)];
|
||||
let mut work = vec![(format_renderer.make_child_renderer(), item)];
|
||||
|
||||
let unknown = rustc_span::Symbol::intern("<unknown item>");
|
||||
while let Some((mut cx, item)) = work.pop() {
|
||||
@ -87,7 +90,7 @@ fn after_krate(
|
||||
};
|
||||
for it in module.items {
|
||||
debug!("Adding {:?} to worklist", it.name);
|
||||
work.push((cx.clone(), it));
|
||||
work.push((cx.make_child_renderer(), it));
|
||||
}
|
||||
|
||||
cx.mod_item_out(&name)?;
|
||||
|
@ -1373,10 +1373,6 @@ pub fn new() -> Self {
|
||||
}
|
||||
}
|
||||
|
||||
crate fn reset(&mut self) {
|
||||
self.map = init_id_map();
|
||||
}
|
||||
|
||||
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(),
|
||||
|
@ -38,15 +38,9 @@ fn test_unique_id() {
|
||||
"assoc_type.Item-1",
|
||||
];
|
||||
|
||||
let map = RefCell::new(IdMap::new());
|
||||
let test = || {
|
||||
let mut map = map.borrow_mut();
|
||||
let actual: Vec<String> = input.iter().map(|s| map.derive(s.to_string())).collect();
|
||||
assert_eq!(&actual[..], expected);
|
||||
};
|
||||
test();
|
||||
map.borrow_mut().reset();
|
||||
test();
|
||||
let mut map = IdMap::new();
|
||||
let actual: Vec<String> = input.iter().map(|s| map.derive(s.to_string())).collect();
|
||||
assert_eq!(&actual[..], expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -40,7 +40,6 @@
|
||||
/// It is intended that this context is a lightweight object which can be fairly
|
||||
/// easily cloned because it is cloned per work-job (about once per item in the
|
||||
/// rustdoc tree).
|
||||
#[derive(Clone)]
|
||||
crate struct Context<'tcx> {
|
||||
/// Current hierarchy of components leading down to what's currently being
|
||||
/// rendered
|
||||
@ -157,11 +156,6 @@ fn render_item(&self, it: &clean::Item, pushname: bool) -> String {
|
||||
static_extra_scripts: &[],
|
||||
};
|
||||
|
||||
{
|
||||
self.id_map.borrow_mut().reset();
|
||||
self.id_map.borrow_mut().populate(&INITIAL_IDS);
|
||||
}
|
||||
|
||||
if !self.render_redirect_pages {
|
||||
layout::render(
|
||||
&self.shared.layout,
|
||||
@ -436,6 +430,21 @@ fn init(
|
||||
Ok((cx, krate))
|
||||
}
|
||||
|
||||
fn make_child_renderer(&self) -> Self {
|
||||
let mut id_map = IdMap::new();
|
||||
id_map.populate(&INITIAL_IDS);
|
||||
|
||||
Self {
|
||||
current: self.current.clone(),
|
||||
dst: self.dst.clone(),
|
||||
render_redirect_pages: self.render_redirect_pages,
|
||||
id_map: Box::new(RefCell::new(id_map)),
|
||||
deref_id_map: Box::new(RefCell::new(FxHashMap::default())),
|
||||
shared: Rc::clone(&self.shared),
|
||||
cache: Rc::clone(&self.cache),
|
||||
}
|
||||
}
|
||||
|
||||
fn after_krate(
|
||||
&mut self,
|
||||
krate: &clean::Crate,
|
||||
|
@ -149,6 +149,10 @@ fn init(
|
||||
))
|
||||
}
|
||||
|
||||
fn make_child_renderer(&self) -> Self {
|
||||
self.clone()
|
||||
}
|
||||
|
||||
/// Inserts an item into the index. This should be used rather than directly calling insert on
|
||||
/// the hashmap because certain items (traits and types) need to have their mappings for trait
|
||||
/// implementations filled out before they're inserted.
|
||||
|
Loading…
Reference in New Issue
Block a user