From b9ae4f7bf7dc4f4a7c8a8cc934522093d6868bf7 Mon Sep 17 00:00:00 2001 From: Ivan Enderlin Date: Fri, 9 Jan 2026 08:55:02 +0100 Subject: [PATCH] rustdoc_json: Remove one call to `std::mem::take` in `after_krate`. This patch removes one call to `std::mem::take` to save two `memcpy`s: `JsonRenderer::index` can be quite large as noted https://github.com/rust-lang/rust/pull/142335. `self.index` can be passed directly to `types::Crate`. This removal makes `self` immutable. The private `serialize_and_write` method is moved as a function: the `self` argument is replaced by `sess: &Session`. This `&Session` was fetched earlier in `after_krate` in all cases. This change allows to call `serialize_and_write` after `output_crate` is created, without having a conflict around the move of `self`: the borrow checker is now happy. --- src/librustdoc/json/mod.rs | 48 +++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index 37d456ae796b..a201f661d9f7 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -104,22 +104,6 @@ impl<'tcx> JsonRenderer<'tcx> { }) .unwrap_or_default() } - - fn serialize_and_write( - &self, - output_crate: types::Crate, - mut writer: BufWriter, - path: &str, - ) -> Result<(), Error> { - self.sess().time("rustdoc_json_serialize_and_write", || { - try_err!( - serde_json::ser::to_writer(&mut writer, &output_crate).map_err(|e| e.to_string()), - path - ); - try_err!(writer.flush(), path); - Ok(()) - }) - } } impl<'tcx> JsonRenderer<'tcx> { @@ -252,26 +236,23 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { unreachable!("RUN_ON_MODULE = false, should never call mod_item_in") } - fn after_krate(mut self) -> Result<(), Error> { + fn after_krate(self) -> Result<(), Error> { debug!("Done with crate"); let e = ExternalCrate { crate_num: LOCAL_CRATE }; - - // We've finished using the index, and don't want to clone it, because it is big. - let index = std::mem::take(&mut self.index); + let sess = self.sess(); // Note that tcx.rust_target_features is inappropriate here because rustdoc tries to run for // multiple targets: https://github.com/rust-lang/rust/pull/137632 // // We want to describe a single target, so pass tcx.sess rather than tcx. - let target = conversions::target(self.tcx.sess); + let target = conversions::target(sess); debug!("Constructing Output"); let output_crate = types::Crate { root: self.id_from_item_default(e.def_id().into()), crate_version: self.cache.crate_version.clone(), includes_private: self.cache.document_private, - index, paths: self .cache .paths @@ -313,6 +294,8 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { ) }) .collect(), + // Be careful to not clone the `index`, it is big. + index: self.index, target, format_version: types::FORMAT_VERSION, }; @@ -323,17 +306,34 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { p.push(output_crate.index.get(&output_crate.root).unwrap().name.clone().unwrap()); p.set_extension("json"); - self.serialize_and_write( + serialize_and_write( + sess, output_crate, try_err!(File::create_buffered(&p), p), &p.display().to_string(), ) } else { - self.serialize_and_write(output_crate, BufWriter::new(stdout().lock()), "") + serialize_and_write(sess, output_crate, BufWriter::new(stdout().lock()), "") } } } +fn serialize_and_write( + sess: &Session, + output_crate: types::Crate, + mut writer: BufWriter, + path: &str, +) -> Result<(), Error> { + sess.time("rustdoc_json_serialize_and_write", || { + try_err!( + serde_json::ser::to_writer(&mut writer, &output_crate).map_err(|e| e.to_string()), + path + ); + try_err!(writer.flush(), path); + Ok(()) + }) +} + // Some nodes are used a lot. Make sure they don't unintentionally get bigger. // // These assertions are here, not in `src/rustdoc-json-types/lib.rs` where the types are defined,