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) {} +}