about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorJ. Ryan Stinnett <jryans@gmail.com>2021-01-28 22:03:20 +0000
committerJ. Ryan Stinnett <jryans@gmail.com>2021-01-30 14:23:50 +0000
commit7e3217845dc5dea331b26efb2bf51b60afae2082 (patch)
treec40c88774ac954d5b09f55aee3b820c53d45c3e5 /src
parent7ce1b3b24491cbe10669cbe2b5733c2fe7cfe5b7 (diff)
downloadrust-7e3217845dc5dea331b26efb2bf51b60afae2082.tar.gz
rust-7e3217845dc5dea331b26efb2bf51b60afae2082.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/librustdoc/html/render/mod.rs18
-rw-r--r--src/test/rustdoc-ui/deref-generic.rs15
2 files changed, 26 insertions, 7 deletions
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index daaa2c719b0..6909ab870db 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<Target = S> 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<Target = S> 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 00000000000..bc64beb1b93
--- /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>(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) {}
+}