about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2024-11-25 16:19:02 +0100
committerGuillaume Gomez <guillaume1.gomez@gmail.com>2024-12-01 21:54:55 +0100
commit5fa1653c5cd175430d14c3c3d8416635772811da (patch)
tree86f888b062b3b4e9469dc5f65b6f9d3fddc9018d
parent2e242f8af312607cb50bcc9b3b02ff1576dcfa9b (diff)
downloadrust-5fa1653c5cd175430d14c3c3d8416635772811da.tar.gz
rust-5fa1653c5cd175430d14c3c3d8416635772811da.zip
Move `SharedContext` out of `Rc`
-rw-r--r--src/librustdoc/html/render/context.rs45
-rw-r--r--src/librustdoc/html/render/mod.rs70
-rw-r--r--src/librustdoc/html/render/print_item.rs117
-rw-r--r--src/librustdoc/html/render/sidebar.rs72
-rw-r--r--src/librustdoc/html/render/write_shared.rs23
-rw-r--r--src/librustdoc/html/sources.rs6
6 files changed, 171 insertions, 162 deletions
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index bc1f0423c17..81a9cce80d1 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -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;
@@ -51,17 +50,17 @@ pub(crate) struct Context<'tcx> {
     pub(crate) dst: PathBuf,
     /// 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: FxIndexSet<clean::Type>,
+    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,
@@ -170,8 +169,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/'
@@ -230,24 +229,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()) {
@@ -572,10 +570,10 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
         let mut cx = Context {
             current: Vec::new(),
             dst,
-            id_map,
+            id_map: RefCell::new(id_map),
             deref_id_map: Default::default(),
-            shared: Rc::new(scx),
-            types_with_notable_traits: FxIndexSet::default(),
+            shared: scx,
+            types_with_notable_traits: RefCell::new(FxIndexSet::default()),
             info: ContextInfo::new(include_sources),
         };
 
@@ -591,9 +589,9 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
     }
 
     fn make_child_renderer(&mut self) -> Self::InfoType {
-        self.deref_id_map.clear();
-        self.id_map.clear();
-        self.types_with_notable_traits.clear();
+        self.deref_id_map.borrow_mut().clear();
+        self.id_map.borrow_mut().clear();
+        self.types_with_notable_traits.borrow_mut().clear();
         self.info
     }
 
@@ -612,7 +610,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",
@@ -759,11 +757,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"), ""))
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 7c5048cd164..f4367257572 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -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\">\
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index a86b7966c26..4c8d704e65b 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -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(_) => {
@@ -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,
diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs
index 76de8d87231..e99e2f04b2c 100644
--- a/src/librustdoc/html/render/sidebar.rs
+++ b/src/librustdoc/html/render/sidebar.rs
@@ -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
diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs
index 1fb589d829e..ce10e5ecc24 100644
--- a/src/librustdoc/html/render/write_shared.rs
+++ b/src/librustdoc/html/render/write_shared.rs
@@ -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());
@@ -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) {
diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs
index 71b110c943e..c37506e3588 100644
--- a/src/librustdoc/html/sources.rs
+++ b/src/librustdoc/html/sources.rs
@@ -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;
@@ -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 },