1
Fork 0

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:
Jonas Schievink 2021-01-31 01:47:38 +01:00 committed by GitHub
commit 4de31816bf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 26 additions and 7 deletions

View file

@ -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);
} }
} }

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