From d882b2118e505d86a9f770ef862fb1ee6e91ced8 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 8 Sep 2023 14:59:54 -0700 Subject: [PATCH] rustdoc: add impl items from aliased type into sidebar --- src/librustdoc/html/render/sidebar.rs | 45 ++++++++++++++++--- tests/rustdoc/issue-32077-type-alias-impls.rs | 5 +++ 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>, impl_: &Impl, - v: &[Impl], + v: impl Iterator, derefs: &mut DefIdSet, used_links: &mut FxHashSet, ) { @@ -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 {} // @!has - '//h3' 'impl Bar for GenericStruct {}' // Same goes for the `Deref` impl. // @!has - '//h2' 'Methods from Deref' +// @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; impl TypedefStruct {