Skip to content

Commit a6fa92c

Browse files
committed
Balance sidebar Deref cycle check with main content
The `Deref` cycle checks added as part of #80653 were "unbalanced" in the sense that the main content code path checks for cycles _before_ descending, while the sidebar checks _after_. Checking _before_ is correct, so this changes the sidebar path to match the main content path.
1 parent 613ef74 commit a6fa92c

File tree

2 files changed

+26
-7
lines changed

2 files changed

+26
-7
lines changed

src/librustdoc/html/render/mod.rs

+11-7
Original file line numberDiff line numberDiff line change
@@ -3518,6 +3518,7 @@ fn render_assoc_items(
35183518
"deref-methods-{:#}",
35193519
type_.print(cx.cache())
35203520
)));
3521+
debug!("Adding {} to deref id map", type_.print(cx.cache()));
35213522
cx.deref_id_map
35223523
.borrow_mut()
35233524
.insert(type_.def_id_full(cx.cache()).unwrap(), id.clone());
@@ -3636,6 +3637,7 @@ fn render_deref_methods(
36363637
_ => None,
36373638
})
36383639
.expect("Expected associated type binding");
3640+
debug!("Render deref methods for {:#?}, target {:#?}", impl_.inner_impl().for_, target);
36393641
let what =
36403642
AssocItemRender::DerefFor { trait_: deref_type, type_: real_target, deref_mut_: deref_mut };
36413643
if let Some(did) = target.def_id_full(cx.cache()) {
@@ -4396,6 +4398,15 @@ fn sidebar_deref_methods(cx: &Context<'_>, impl_: &Impl, v: &Vec<Impl>) -> Strin
43964398
})
43974399
{
43984400
debug!("found target, real_target: {:?} {:?}", target, real_target);
4401+
if let Some(did) = target.def_id_full(cx.cache()) {
4402+
if let Some(type_did) = impl_.inner_impl().for_.def_id_full(cx.cache()) {
4403+
// `impl Deref<Target = S> for S`
4404+
if did == type_did {
4405+
// Avoid infinite cycles
4406+
return out;
4407+
}
4408+
}
4409+
}
43994410
let deref_mut = v
44004411
.iter()
44014412
.filter(|i| i.inner_impl().trait_.is_some())
@@ -4439,13 +4450,6 @@ fn sidebar_deref_methods(cx: &Context<'_>, impl_: &Impl, v: &Vec<Impl>) -> Strin
44394450
.filter(|i| i.inner_impl().trait_.is_some())
44404451
.find(|i| i.inner_impl().trait_.def_id_full(cx.cache()) == c.deref_trait_did)
44414452
{
4442-
if let Some(type_did) = impl_.inner_impl().for_.def_id_full(cx.cache()) {
4443-
// `impl Deref<Target = S> for S`
4444-
if target_did == type_did {
4445-
// Avoid infinite cycles
4446-
return out;
4447-
}
4448-
}
44494453
out.push_str(&sidebar_deref_methods(cx, target_deref_impl, target_impls));
44504454
}
44514455
}

src/test/rustdoc-ui/deref-generic.rs

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// check-pass
2+
// #81395: Fix ICE when recursing into Deref target only differing in type args
3+
4+
pub struct Generic<T>(T);
5+
6+
impl<'a> std::ops::Deref for Generic<&'a mut ()> {
7+
type Target = Generic<&'a ()>;
8+
fn deref(&self) -> &Self::Target {
9+
unimplemented!()
10+
}
11+
}
12+
13+
impl<'a> Generic<&'a ()> {
14+
pub fn some_method(&self) {}
15+
}

0 commit comments

Comments
 (0)