From aee50f417f38ce57f2491ee86fb386e7d32f241c Mon Sep 17 00:00:00 2001 From: Trinity Pointard Date: Tue, 15 Jun 2021 11:47:17 +0200 Subject: [PATCH 1/3] fix rustdoc stack overflow on mutually recursive Deref fix #85095 --- src/librustdoc/html/render/mod.rs | 20 +++++++++++++++++--- src/test/rustdoc/issue-85095.rs | 22 ++++++++++++++++++++++ 2 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 src/test/rustdoc/issue-85095.rs diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index ebb4cfb7d48bd..7e53cf231a14e 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1960,13 +1960,19 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) { .filter(|i| i.inner_impl().trait_.is_some()) .find(|i| i.inner_impl().trait_.def_id_full(cache) == cx.cache.deref_trait_did) { - sidebar_deref_methods(cx, out, impl_, v); + sidebar_deref_methods(cx, out, impl_, v, FxHashSet::default()); } } } } -fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &Vec) { +fn sidebar_deref_methods( + cx: &Context<'_>, + out: &mut Buffer, + impl_: &Impl, + v: &Vec, + mut already_seen: FxHashSet, +) { let c = cx.cache(); debug!("found Deref: {:?}", impl_); @@ -2032,7 +2038,15 @@ 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(c) == c.deref_trait_did) { - sidebar_deref_methods(cx, out, target_deref_impl, target_impls); + if already_seen.insert(target_did.clone()) { + sidebar_deref_methods( + cx, + out, + target_deref_impl, + target_impls, + already_seen, + ); + } } } } diff --git a/src/test/rustdoc/issue-85095.rs b/src/test/rustdoc/issue-85095.rs new file mode 100644 index 0000000000000..5c4a1da9e596d --- /dev/null +++ b/src/test/rustdoc/issue-85095.rs @@ -0,0 +1,22 @@ +use std::ops::Deref; + +pub struct A; +pub struct B; + +// @has issue_85095/struct.A.html '//code' 'impl Deref for A' +impl Deref for A { + type Target = B; + + fn deref(&self) -> &Self::Target { + panic!() + } +} + +// @has issue_85095/struct.B.html '//code' 'impl Deref for B' +impl Deref for B { + type Target = A; + + fn deref(&self) -> &Self::Target { + panic!() + } +} From 2d76d44eaefc2859c0e5d7645f7a543cd15d5320 Mon Sep 17 00:00:00 2001 From: Trinity Pointard Date: Tue, 15 Jun 2021 14:30:14 +0200 Subject: [PATCH 2/3] remove code for recursive Deref in sidebar fix #85037 --- src/librustdoc/html/render/mod.rs | 31 ++----------------------------- src/test/rustdoc/issue-85037.rs | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+), 29 deletions(-) create mode 100644 src/test/rustdoc/issue-85037.rs diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 7e53cf231a14e..54171733c30f6 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1960,19 +1960,13 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) { .filter(|i| i.inner_impl().trait_.is_some()) .find(|i| i.inner_impl().trait_.def_id_full(cache) == cx.cache.deref_trait_did) { - sidebar_deref_methods(cx, out, impl_, v, FxHashSet::default()); + sidebar_deref_methods(cx, out, impl_, v); } } } } -fn sidebar_deref_methods( - cx: &Context<'_>, - out: &mut Buffer, - impl_: &Impl, - v: &Vec, - mut already_seen: FxHashSet, -) { +fn sidebar_deref_methods(cx: &Context<'_>, out: &mut Buffer, impl_: &Impl, v: &Vec) { let c = cx.cache(); debug!("found Deref: {:?}", impl_); @@ -2029,27 +2023,6 @@ fn sidebar_deref_methods( out.push_str(""); } } - - // Recurse into any further impls that might exist for `target` - if let Some(target_did) = target.def_id_full(c) { - if let Some(target_impls) = c.impls.get(&target_did) { - if let Some(target_deref_impl) = target_impls - .iter() - .filter(|i| i.inner_impl().trait_.is_some()) - .find(|i| i.inner_impl().trait_.def_id_full(c) == c.deref_trait_did) - { - if already_seen.insert(target_did.clone()) { - sidebar_deref_methods( - cx, - out, - target_deref_impl, - target_impls, - already_seen, - ); - } - } - } - } } } diff --git a/src/test/rustdoc/issue-85037.rs b/src/test/rustdoc/issue-85037.rs new file mode 100644 index 0000000000000..86bd246a878cc --- /dev/null +++ b/src/test/rustdoc/issue-85037.rs @@ -0,0 +1,22 @@ +use std::ops::Deref; + +pub struct A {} +impl A { pub fn foo_a(&self) {} } + +pub struct B {} +impl B { pub fn foo_b(&self) {} } + +pub struct C {} +impl C { pub fn foo_c(&self) {} } + +// @has issue_85037/struct.A.html '//div[@class="sidebar-links"]' 'foo_b' +impl Deref for A { + type Target = B; + fn deref(&self) -> &B { todo!() } +} + +// @!has issue_85037/struct.A.html '//div[@class="sidebar-links"]' 'foo_c' +impl Deref for B { + type Target = C; + fn deref(&self) -> &C { todo!() } +} From 5f7d44171de8b84558fc76a0f305d83fd6fa34f3 Mon Sep 17 00:00:00 2001 From: Trinity Pointard Date: Wed, 16 Jun 2021 14:42:51 +0200 Subject: [PATCH 3/3] rename test-cases --- .../rustdoc/{issue-85037.rs => recursive-deref-sidebar.rs} | 4 ++-- src/test/rustdoc/{issue-85095.rs => recursive-deref.rs} | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) rename src/test/rustdoc/{issue-85037.rs => recursive-deref-sidebar.rs} (66%) rename src/test/rustdoc/{issue-85095.rs => recursive-deref.rs} (66%) diff --git a/src/test/rustdoc/issue-85037.rs b/src/test/rustdoc/recursive-deref-sidebar.rs similarity index 66% rename from src/test/rustdoc/issue-85037.rs rename to src/test/rustdoc/recursive-deref-sidebar.rs index 86bd246a878cc..fcb636ade8f7a 100644 --- a/src/test/rustdoc/issue-85037.rs +++ b/src/test/rustdoc/recursive-deref-sidebar.rs @@ -9,13 +9,13 @@ impl B { pub fn foo_b(&self) {} } pub struct C {} impl C { pub fn foo_c(&self) {} } -// @has issue_85037/struct.A.html '//div[@class="sidebar-links"]' 'foo_b' +// @has recursive_deref_sidebar/struct.A.html '//div[@class="sidebar-links"]' 'foo_b' impl Deref for A { type Target = B; fn deref(&self) -> &B { todo!() } } -// @!has issue_85037/struct.A.html '//div[@class="sidebar-links"]' 'foo_c' +// @!has recursive_deref_sidebar/struct.A.html '//div[@class="sidebar-links"]' 'foo_c' impl Deref for B { type Target = C; fn deref(&self) -> &C { todo!() } diff --git a/src/test/rustdoc/issue-85095.rs b/src/test/rustdoc/recursive-deref.rs similarity index 66% rename from src/test/rustdoc/issue-85095.rs rename to src/test/rustdoc/recursive-deref.rs index 5c4a1da9e596d..91db01177c581 100644 --- a/src/test/rustdoc/issue-85095.rs +++ b/src/test/rustdoc/recursive-deref.rs @@ -3,7 +3,7 @@ use std::ops::Deref; pub struct A; pub struct B; -// @has issue_85095/struct.A.html '//code' 'impl Deref for A' +// @has recursive_deref/struct.A.html '//code' 'impl Deref for A' impl Deref for A { type Target = B; @@ -12,7 +12,7 @@ impl Deref for A { } } -// @has issue_85095/struct.B.html '//code' 'impl Deref for B' +// @has recursive_deref/struct.B.html '//code' 'impl Deref for B' impl Deref for B { type Target = A;