about summary refs log tree commit diff
diff options
context:
space:
mode:
authorCamelid <camelidcamel@gmail.com>2021-03-01 19:12:03 -0800
committerCamelid <camelidcamel@gmail.com>2021-03-05 19:41:37 -0800
commitc09d9d34f02c72b93da25ba27758db7d7cddb1f4 (patch)
treeb37de07db02a7a62b1415ee89a84d87ec85a8aed
parentff39c46959b0c6926c0199f59f65af585e131e7d (diff)
downloadrust-c09d9d34f02c72b93da25ba27758db7d7cddb1f4.tar.gz
rust-c09d9d34f02c72b93da25ba27758db7d7cddb1f4.zip
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.
-rw-r--r--src/librustdoc/formats/renderer.rs9
-rw-r--r--src/librustdoc/html/markdown.rs4
-rw-r--r--src/librustdoc/html/markdown/tests.rs12
-rw-r--r--src/librustdoc/html/render/context.rs21
-rw-r--r--src/librustdoc/json/mod.rs4
5 files changed, 28 insertions, 22 deletions
diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs
index b779363e5c7..9b0d193a0bc 100644
--- a/src/librustdoc/formats/renderer.rs
+++ b/src/librustdoc/formats/renderer.rs
@@ -9,7 +9,7 @@ use crate::formats::cache::Cache;
 /// 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 @@ crate trait FormatRenderer<'tcx>: Clone {
         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 @@ crate fn run_format<'tcx, T: FormatRenderer<'tcx>>(
     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 @@ crate fn run_format<'tcx, T: FormatRenderer<'tcx>>(
             };
             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)?;
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index f8ca259fb9a..ccc51c243ad 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -1373,10 +1373,6 @@ impl IdMap {
         }
     }
 
-    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(),
diff --git a/src/librustdoc/html/markdown/tests.rs b/src/librustdoc/html/markdown/tests.rs
index 59ca841715c..e016d2c3ab0 100644
--- a/src/librustdoc/html/markdown/tests.rs
+++ b/src/librustdoc/html/markdown/tests.rs
@@ -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]
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 23c2a925105..41d4aef7c7a 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -40,7 +40,6 @@ use crate::html::{layout, sources};
 /// 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 @@ impl<'tcx> Context<'tcx> {
             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 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
         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,
diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs
index e6edf33d23c..406c57826a0 100644
--- a/src/librustdoc/json/mod.rs
+++ b/src/librustdoc/json/mod.rs
@@ -149,6 +149,10 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
         ))
     }
 
+    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.