diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index daaa2c719b0e6..6909ab870db61 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -3510,6 +3510,7 @@ fn render_assoc_items(
"deref-methods-{:#}",
type_.print(cx.cache())
)));
+ debug!("Adding {} to deref id map", type_.print(cx.cache()));
cx.deref_id_map
.borrow_mut()
.insert(type_.def_id_full(cx.cache()).unwrap(), id.clone());
@@ -3626,6 +3627,7 @@ fn render_deref_methods(
_ => None,
})
.expect("Expected associated type binding");
+ debug!("Render deref methods for {:#?}, target {:#?}", impl_.inner_impl().for_, target);
let what =
AssocItemRender::DerefFor { trait_: deref_type, type_: real_target, deref_mut_: deref_mut };
if let Some(did) = target.def_id_full(cx.cache()) {
@@ -4416,6 +4418,15 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V
})
{
debug!("found target, real_target: {:?} {:?}", target, real_target);
+ if let Some(did) = target.def_id_full(cx.cache()) {
+ if let Some(type_did) = impl_.inner_impl().for_.def_id_full(cx.cache()) {
+ // `impl Deref for S`
+ if did == type_did {
+ // Avoid infinite cycles
+ return;
+ }
+ }
+ }
let deref_mut = v
.iter()
.filter(|i| i.inner_impl().trait_.is_some())
@@ -4464,13 +4475,6 @@ fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &V
.filter(|i| i.inner_impl().trait_.is_some())
.find(|i| i.inner_impl().trait_.def_id_full(cx.cache()) == c.deref_trait_did)
{
- if let Some(type_did) = impl_.inner_impl().for_.def_id_full(cx.cache()) {
- // `impl Deref for S`
- if target_did == type_did {
- // Avoid infinite cycles
- return;
- }
- }
sidebar_deref_methods(cx, out, target_deref_impl, target_impls);
}
}
diff --git a/src/test/rustdoc-ui/deref-generic.rs b/src/test/rustdoc-ui/deref-generic.rs
new file mode 100644
index 0000000000000..bc64beb1b939d
--- /dev/null
+++ b/src/test/rustdoc-ui/deref-generic.rs
@@ -0,0 +1,15 @@
+// check-pass
+// #81395: Fix ICE when recursing into Deref target only differing in type args
+
+pub struct Generic(T);
+
+impl<'a> std::ops::Deref for Generic<&'a mut ()> {
+ type Target = Generic<&'a ()>;
+ fn deref(&self) -> &Self::Target {
+ unimplemented!()
+ }
+}
+
+impl<'a> Generic<&'a ()> {
+ pub fn some_method(&self) {}
+}