about summary refs log tree commit diff
path: root/src/librustdoc/formats/renderer.rs
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2024-11-21 15:16:36 +0100
committerGuillaume Gomez <guillaume1.gomez@gmail.com>2024-12-01 21:54:54 +0100
commit8047340599763eeca43a0dcee1b1f6b65b6d4ecd (patch)
treebba43e7bd82d24bde660fc8b363cdceb8440d1ad /src/librustdoc/formats/renderer.rs
parent1555074ca98de5a827411cf7d7a11779bcfc90f2 (diff)
downloadrust-8047340599763eeca43a0dcee1b1f6b65b6d4ecd.tar.gz
rust-8047340599763eeca43a0dcee1b1f6b65b6d4ecd.zip
Stop cloning `Context` so much
Diffstat (limited to 'src/librustdoc/formats/renderer.rs')
-rw-r--r--src/librustdoc/formats/renderer.rs72
1 files changed, 40 insertions, 32 deletions
diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs
index edd7d56b179..f7ba5bff51b 100644
--- a/src/librustdoc/formats/renderer.rs
+++ b/src/librustdoc/formats/renderer.rs
@@ -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,7 @@ pub(crate) trait FormatRenderer<'tcx>: Sized {
     ///
     /// This is true for html, and false for json. See #80664
     const RUN_ON_MODULE: bool;
+    type InfoType;
 
     /// Sets up any state required for the renderer. When this is called the cache has already been
     /// populated.
@@ -28,7 +29,8 @@ pub(crate) trait FormatRenderer<'tcx>: Sized {
     ) -> 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;
+    fn make_child_renderer(&mut self) -> Self::InfoType;
+    fn set_back_info(&mut self, _info: Self::InfoType);
 
     /// 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 +49,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.make_child_renderer();
+            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 +102,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)];
-
-    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))?;
-        }
-    }
+    run_format_inner(&mut format_renderer, krate.module, prof)?;
+
     prof.verbose_generic_activity_with_arg("renderer_after_krate", T::descr())
         .run(|| format_renderer.after_krate())
 }