about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Howell <michael@notriddle.com>2023-09-08 14:59:54 -0700
committerMichael Howell <michael@notriddle.com>2023-09-08 14:59:54 -0700
commitd882b2118e505d86a9f770ef862fb1ee6e91ced8 (patch)
tree412c6d659e499597aafa0cb4445561de943af27b
parentffc48e3eda36e288f76b4022d72d94321887ebf5 (diff)
downloadrust-d882b2118e505d86a9f770ef862fb1ee6e91ced8.tar.gz
rust-d882b2118e505d86a9f770ef862fb1ee6e91ced8.zip
rustdoc: add impl items from aliased type into sidebar
-rw-r--r--src/librustdoc/html/render/sidebar.rs45
-rw-r--r--tests/rustdoc/issue-32077-type-alias-impls.rs5
2 files changed, 45 insertions, 5 deletions
diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs
index fce31a8423d..949bd5219d7 100644
--- a/src/librustdoc/html/render/sidebar.rs
+++ b/src/librustdoc/html/render/sidebar.rs
@@ -3,10 +3,12 @@ use std::{borrow::Cow, rc::Rc};
 use askama::Template;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::{def::CtorKind, def_id::DefIdSet};
+use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
 use rustc_middle::ty::{self, TyCtxt};
 
 use crate::{
     clean,
+    clean::types::TypeAliasItem,
     formats::{item_type::ItemType, Impl},
     html::{format::Buffer, markdown::IdMap},
 };
@@ -279,10 +281,43 @@ fn sidebar_assoc_items<'a>(
 ) {
     let did = it.item_id.expect_def_id();
     let cache = cx.cache();
+    let tcx = cx.tcx();
+    let mut v: Vec<&Impl> =
+        cache.impls.get(&did).map(Vec::as_slice).unwrap_or(&[]).iter().collect();
+    if let TypeAliasItem(ait) = &*it.kind &&
+        let aliased_clean_type = ait.item_type.as_ref().unwrap_or(&ait.type_) &&
+        let Some(aliased_type_defid) = aliased_clean_type.def_id(cache) &&
+        let Some(av) = cache.impls.get(&aliased_type_defid) &&
+        let Some(alias_def_id) = it.item_id.as_def_id()
+    {
+        // This branch of the compiler compares types structually, but does
+        // not check trait bounds. That's probably fine, since type aliases
+        // don't normally constrain on them anyway.
+        // https://github.com/rust-lang/rust/issues/21903
+        //
+        // FIXME(lazy_type_alias): Once the feature is complete or stable, rewrite this to use type unification.
+        // Be aware of `tests/rustdoc/issue-112515-impl-ty-alias.rs` which might regress.
+        let aliased_ty = tcx.type_of(alias_def_id).skip_binder();
+        let reject_cx = DeepRejectCtxt {
+            treat_obligation_params: TreatParams::AsCandidateKey,
+        };
+        v.extend(av.iter().filter(|impl_| {
+            if let Some(impl_def_id) = impl_.impl_item.item_id.as_def_id() {
+                reject_cx.types_may_unify(aliased_ty, tcx.type_of(impl_def_id).skip_binder())
+            } else {
+                false
+            }
+        }));
+    }
+    let v = {
+        let mut saw_impls = FxHashSet::default();
+        v.retain(|i| saw_impls.insert(i.def_id()));
+        v.as_slice()
+    };
 
     let mut assoc_consts = Vec::new();
     let mut methods = Vec::new();
-    if let Some(v) = cache.impls.get(&did) {
+    if !v.is_empty() {
         let mut used_links = FxHashSet::default();
         let mut id_map = IdMap::new();
 
@@ -318,7 +353,7 @@ fn sidebar_assoc_items<'a>(
                     cx,
                     &mut deref_methods,
                     impl_,
-                    v,
+                    v.iter().copied(),
                     &mut derefs,
                     &mut used_links,
                 );
@@ -348,7 +383,7 @@ fn sidebar_deref_methods<'a>(
     cx: &'a Context<'_>,
     out: &mut Vec<LinkBlock<'a>>,
     impl_: &Impl,
-    v: &[Impl],
+    v: impl Iterator<Item = &'a Impl>,
     derefs: &mut DefIdSet,
     used_links: &mut FxHashSet<String>,
 ) {
@@ -373,7 +408,7 @@ fn sidebar_deref_methods<'a>(
             // Avoid infinite cycles
             return;
         }
-        let deref_mut = v.iter().any(|i| i.trait_did() == cx.tcx().lang_items().deref_mut_trait());
+        let deref_mut = { v }.any(|i| i.trait_did() == cx.tcx().lang_items().deref_mut_trait());
         let inner_impl = target
             .def_id(c)
             .or_else(|| {
@@ -424,7 +459,7 @@ fn sidebar_deref_methods<'a>(
                 cx,
                 out,
                 target_deref_impl,
-                target_impls,
+                target_impls.iter(),
                 derefs,
                 used_links,
             );
diff --git a/tests/rustdoc/issue-32077-type-alias-impls.rs b/tests/rustdoc/issue-32077-type-alias-impls.rs
index 555d0579bee..26778c67c24 100644
--- a/tests/rustdoc/issue-32077-type-alias-impls.rs
+++ b/tests/rustdoc/issue-32077-type-alias-impls.rs
@@ -29,6 +29,11 @@ impl Bar for GenericStruct<u32> {}
 // @!has - '//h3' 'impl Bar for GenericStruct<u32> {}'
 // Same goes for the `Deref` impl.
 // @!has - '//h2' 'Methods from Deref<Target = u32>'
+// @count - '//nav[@class="sidebar"]//a' 'on_alias' 1
+// @count - '//nav[@class="sidebar"]//a' 'on_gen' 1
+// @count - '//nav[@class="sidebar"]//a' 'Foo' 1
+// @!has - '//nav[@class="sidebar"]//a' 'Bar'
+// @!has - '//nav[@class="sidebar"]//a' 'on_u32'
 pub type TypedefStruct = GenericStruct<u8>;
 
 impl TypedefStruct {