Rollup merge of #81491 - jryans:rustdoc-deref-ice-81395, r=GuillaumeGomez
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. Fixes #81395 r? ```@GuillaumeGomez```
This commit is contained in:
commit
4de31816bf
2 changed files with 26 additions and 7 deletions
|
@ -3510,6 +3510,7 @@ fn render_assoc_items(
|
||||||
"deref-methods-{:#}",
|
"deref-methods-{:#}",
|
||||||
type_.print(cx.cache())
|
type_.print(cx.cache())
|
||||||
)));
|
)));
|
||||||
|
debug!("Adding {} to deref id map", type_.print(cx.cache()));
|
||||||
cx.deref_id_map
|
cx.deref_id_map
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.insert(type_.def_id_full(cx.cache()).unwrap(), id.clone());
|
.insert(type_.def_id_full(cx.cache()).unwrap(), id.clone());
|
||||||
|
@ -3626,6 +3627,7 @@ fn render_deref_methods(
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.expect("Expected associated type binding");
|
.expect("Expected associated type binding");
|
||||||
|
debug!("Render deref methods for {:#?}, target {:#?}", impl_.inner_impl().for_, target);
|
||||||
let what =
|
let what =
|
||||||
AssocItemRender::DerefFor { trait_: deref_type, type_: real_target, deref_mut_: deref_mut };
|
AssocItemRender::DerefFor { trait_: deref_type, type_: real_target, deref_mut_: deref_mut };
|
||||||
if let Some(did) = target.def_id_full(cx.cache()) {
|
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);
|
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<Target = S> for S`
|
||||||
|
if did == type_did {
|
||||||
|
// Avoid infinite cycles
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
let deref_mut = v
|
let deref_mut = v
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|i| i.inner_impl().trait_.is_some())
|
.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())
|
.filter(|i| i.inner_impl().trait_.is_some())
|
||||||
.find(|i| i.inner_impl().trait_.def_id_full(cx.cache()) == c.deref_trait_did)
|
.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<Target = S> for S`
|
|
||||||
if target_did == type_did {
|
|
||||||
// Avoid infinite cycles
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sidebar_deref_methods(cx, out, target_deref_impl, target_impls);
|
sidebar_deref_methods(cx, out, target_deref_impl, target_impls);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
15
src/test/rustdoc-ui/deref-generic.rs
Normal file
15
src/test/rustdoc-ui/deref-generic.rs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// check-pass
|
||||||
|
// #81395: Fix ICE when recursing into Deref target only differing in type args
|
||||||
|
|
||||||
|
pub struct Generic<T>(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) {}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue