diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 1ce6a5c00be74..826e7782db1e9 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -6,7 +6,7 @@ use std::rc::Rc;
use std::sync::mpsc::{channel, Receiver};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_hir::def_id::LOCAL_CRATE;
+use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
use rustc_span::edition::Edition;
@@ -54,6 +54,9 @@ crate struct Context<'tcx> {
/// real location of an item. This is used to allow external links to
/// publicly reused items to redirect to the right location.
pub(super) render_redirect_pages: bool,
+ /// Tracks section IDs for `Deref` targets so they match in both the main
+ /// body and the sidebar.
+ pub(super) deref_id_map: RefCell>,
/// The map used to ensure all generated 'id=' attributes are unique.
pub(super) id_map: RefCell,
/// Shared mutable state.
@@ -70,7 +73,7 @@ crate struct Context<'tcx> {
// `Context` is cloned a lot, so we don't want the size to grow unexpectedly.
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-rustc_data_structures::static_assert_size!(Context<'_>, 104);
+rustc_data_structures::static_assert_size!(Context<'_>, 144);
/// Shared mutable state used in [`Context`] and elsewhere.
crate struct SharedContext<'tcx> {
@@ -513,6 +516,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
dst,
render_redirect_pages: false,
id_map: RefCell::new(id_map),
+ deref_id_map: RefCell::new(FxHashMap::default()),
shared: Rc::new(scx),
include_sources,
};
@@ -536,6 +540,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
current: self.current.clone(),
dst: self.dst.clone(),
render_redirect_pages: self.render_redirect_pages,
+ deref_id_map: RefCell::new(FxHashMap::default()),
id_map: RefCell::new(IdMap::new()),
shared: Rc::clone(&self.shared),
include_sources: self.include_sources,
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index e2ecf20fe848b..f78129050d7ec 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -1054,6 +1054,19 @@ fn render_assoc_items(
containing_item: &clean::Item,
it: DefId,
what: AssocItemRender<'_>,
+) {
+ let mut derefs = FxHashSet::default();
+ derefs.insert(it);
+ render_assoc_items_inner(w, cx, containing_item, it, what, &mut derefs)
+}
+
+fn render_assoc_items_inner(
+ w: &mut Buffer,
+ cx: &Context<'_>,
+ containing_item: &clean::Item,
+ it: DefId,
+ what: AssocItemRender<'_>,
+ derefs: &mut FxHashSet,
) {
info!("Documenting associated items of {:?}", containing_item.name);
let cache = cx.cache();
@@ -1063,9 +1076,10 @@ fn render_assoc_items(
};
let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none());
if !non_trait.is_empty() {
+ let mut tmp_buf = Buffer::empty_from(w);
let render_mode = match what {
AssocItemRender::All => {
- w.write_str(
+ tmp_buf.write_str(
"",
@@ -1073,21 +1087,28 @@ fn render_assoc_items(
RenderMode::Normal
}
AssocItemRender::DerefFor { trait_, type_, deref_mut_ } => {
+ let id =
+ cx.derive_id(small_url_encode(format!("deref-methods-{:#}", type_.print(cx))));
+ if let Some(def_id) = type_.def_id(cx.cache()) {
+ cx.deref_id_map.borrow_mut().insert(def_id, id.clone());
+ }
write!(
- w,
- "