Auto merge of #115682 - notriddle:notriddle/impl-sidebar, r=GuillaumeGomez
rustdoc: add impl items from aliased type into sidebar Follow-up of https://github.com/rust-lang/rust/pull/115201.
This commit is contained in:
commit
030e4d382f
@ -7,8 +7,10 @@
|
|||||||
|
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_hir::def_id::{DefIdMap, LOCAL_CRATE};
|
use rustc_hir::def_id::{DefIdMap, LOCAL_CRATE};
|
||||||
|
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
|
use rustc_span::def_id::DefId;
|
||||||
use rustc_span::edition::Edition;
|
use rustc_span::edition::Edition;
|
||||||
use rustc_span::source_map::FileName;
|
use rustc_span::source_map::FileName;
|
||||||
use rustc_span::{sym, Symbol};
|
use rustc_span::{sym, Symbol};
|
||||||
@ -22,13 +24,13 @@
|
|||||||
sidebar::{sidebar_module_like, Sidebar},
|
sidebar::{sidebar_module_like, Sidebar},
|
||||||
AllTypes, LinkFromSrc, StylePath,
|
AllTypes, LinkFromSrc, StylePath,
|
||||||
};
|
};
|
||||||
use crate::clean::{self, types::ExternalLocation, ExternalCrate};
|
use crate::clean::{self, types::ExternalLocation, ExternalCrate, TypeAliasItem};
|
||||||
use crate::config::{ModuleSorting, RenderOptions};
|
use crate::config::{ModuleSorting, RenderOptions};
|
||||||
use crate::docfs::{DocFS, PathError};
|
use crate::docfs::{DocFS, PathError};
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::formats::cache::Cache;
|
use crate::formats::cache::Cache;
|
||||||
use crate::formats::item_type::ItemType;
|
use crate::formats::item_type::ItemType;
|
||||||
use crate::formats::FormatRenderer;
|
use crate::formats::{self, FormatRenderer};
|
||||||
use crate::html::escape::Escape;
|
use crate::html::escape::Escape;
|
||||||
use crate::html::format::{join_with_double_colon, Buffer};
|
use crate::html::format::{join_with_double_colon, Buffer};
|
||||||
use crate::html::markdown::{self, plain_text_summary, ErrorCodes, IdMap};
|
use crate::html::markdown::{self, plain_text_summary, ErrorCodes, IdMap};
|
||||||
@ -147,6 +149,53 @@ pub(crate) fn ensure_dir(&self, dst: &Path) -> Result<(), Error> {
|
|||||||
pub(crate) fn edition(&self) -> Edition {
|
pub(crate) fn edition(&self) -> Edition {
|
||||||
self.tcx.sess.edition()
|
self.tcx.sess.edition()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a list of impls on the given type, and, if it's a type alias,
|
||||||
|
/// other types that it aliases.
|
||||||
|
pub(crate) fn all_impls_for_item<'a>(
|
||||||
|
&'a self,
|
||||||
|
it: &clean::Item,
|
||||||
|
did: DefId,
|
||||||
|
) -> Vec<&'a formats::Impl> {
|
||||||
|
let tcx = self.tcx;
|
||||||
|
let cache = &self.cache;
|
||||||
|
let mut saw_impls = FxHashSet::default();
|
||||||
|
let mut v: Vec<&formats::Impl> = cache
|
||||||
|
.impls
|
||||||
|
.get(&did)
|
||||||
|
.map(Vec::as_slice)
|
||||||
|
.unwrap_or(&[])
|
||||||
|
.iter()
|
||||||
|
.filter(|i| saw_impls.insert(i.def_id()))
|
||||||
|
.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())
|
||||||
|
&& saw_impls.insert(impl_def_id)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
v
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Context<'tcx> {
|
impl<'tcx> Context<'tcx> {
|
||||||
|
@ -54,7 +54,6 @@
|
|||||||
use rustc_hir::def_id::{DefId, DefIdSet};
|
use rustc_hir::def_id::{DefId, DefIdSet};
|
||||||
use rustc_hir::Mutability;
|
use rustc_hir::Mutability;
|
||||||
use rustc_middle::middle::stability;
|
use rustc_middle::middle::stability;
|
||||||
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
|
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_span::{
|
use rustc_span::{
|
||||||
symbol::{sym, Symbol},
|
symbol::{sym, Symbol},
|
||||||
@ -63,7 +62,6 @@
|
|||||||
use serde::ser::{SerializeMap, SerializeSeq};
|
use serde::ser::{SerializeMap, SerializeSeq};
|
||||||
use serde::{Serialize, Serializer};
|
use serde::{Serialize, Serializer};
|
||||||
|
|
||||||
use crate::clean::types::TypeAliasItem;
|
|
||||||
use crate::clean::{self, ItemId, RenderedLink, SelfTy};
|
use crate::clean::{self, ItemId, RenderedLink, SelfTy};
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::formats::cache::Cache;
|
use crate::formats::cache::Cache;
|
||||||
@ -1119,13 +1117,13 @@ pub(crate) fn render_all_impls(
|
|||||||
fn render_assoc_items<'a, 'cx: 'a>(
|
fn render_assoc_items<'a, 'cx: 'a>(
|
||||||
cx: &'a mut Context<'cx>,
|
cx: &'a mut Context<'cx>,
|
||||||
containing_item: &'a clean::Item,
|
containing_item: &'a clean::Item,
|
||||||
it: DefId,
|
did: DefId,
|
||||||
what: AssocItemRender<'a>,
|
what: AssocItemRender<'a>,
|
||||||
) -> impl fmt::Display + 'a + Captures<'cx> {
|
) -> impl fmt::Display + 'a + Captures<'cx> {
|
||||||
let mut derefs = DefIdSet::default();
|
let mut derefs = DefIdSet::default();
|
||||||
derefs.insert(it);
|
derefs.insert(did);
|
||||||
display_fn(move |f| {
|
display_fn(move |f| {
|
||||||
render_assoc_items_inner(f, cx, containing_item, it, what, &mut derefs);
|
render_assoc_items_inner(f, cx, containing_item, did, what, &mut derefs);
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -1134,46 +1132,16 @@ fn render_assoc_items_inner(
|
|||||||
mut w: &mut dyn fmt::Write,
|
mut w: &mut dyn fmt::Write,
|
||||||
cx: &mut Context<'_>,
|
cx: &mut Context<'_>,
|
||||||
containing_item: &clean::Item,
|
containing_item: &clean::Item,
|
||||||
it: DefId,
|
did: DefId,
|
||||||
what: AssocItemRender<'_>,
|
what: AssocItemRender<'_>,
|
||||||
derefs: &mut DefIdSet,
|
derefs: &mut DefIdSet,
|
||||||
) {
|
) {
|
||||||
info!("Documenting associated items of {:?}", containing_item.name);
|
info!("Documenting associated items of {:?}", containing_item.name);
|
||||||
let shared = Rc::clone(&cx.shared);
|
let shared = Rc::clone(&cx.shared);
|
||||||
let cache = &shared.cache;
|
let v = shared.all_impls_for_item(containing_item, did);
|
||||||
let tcx = cx.tcx();
|
let v = v.as_slice();
|
||||||
let av = if let TypeAliasItem(ait) = &*containing_item.kind &&
|
let (non_trait, traits): (Vec<&Impl>, _) =
|
||||||
let aliased_clean_type = ait.item_type.as_ref().unwrap_or(&ait.type_) &&
|
v.iter().partition(|i| i.inner_impl().trait_.is_none());
|
||||||
let Some(aliased_type_defid) = aliased_clean_type.def_id(cache) &&
|
|
||||||
let Some(mut av) = cache.impls.get(&aliased_type_defid).cloned() &&
|
|
||||||
let Some(alias_def_id) = containing_item.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,
|
|
||||||
};
|
|
||||||
av.retain(|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
|
|
||||||
}
|
|
||||||
});
|
|
||||||
av
|
|
||||||
} else {
|
|
||||||
Vec::new()
|
|
||||||
};
|
|
||||||
let blank = Vec::new();
|
|
||||||
let v = cache.impls.get(&it).unwrap_or(&blank);
|
|
||||||
let (non_trait, traits): (Vec<_>, _) =
|
|
||||||
v.iter().chain(&av[..]).partition(|i| i.inner_impl().trait_.is_none());
|
|
||||||
let mut saw_impls = FxHashSet::default();
|
let mut saw_impls = FxHashSet::default();
|
||||||
if !non_trait.is_empty() {
|
if !non_trait.is_empty() {
|
||||||
let mut tmp_buf = Buffer::html();
|
let mut tmp_buf = Buffer::html();
|
||||||
|
@ -278,11 +278,12 @@ fn sidebar_assoc_items<'a>(
|
|||||||
links: &mut Vec<LinkBlock<'a>>,
|
links: &mut Vec<LinkBlock<'a>>,
|
||||||
) {
|
) {
|
||||||
let did = it.item_id.expect_def_id();
|
let did = it.item_id.expect_def_id();
|
||||||
let cache = cx.cache();
|
let v = cx.shared.all_impls_for_item(it, it.item_id.expect_def_id());
|
||||||
|
let v = v.as_slice();
|
||||||
|
|
||||||
let mut assoc_consts = Vec::new();
|
let mut assoc_consts = Vec::new();
|
||||||
let mut methods = 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 used_links = FxHashSet::default();
|
||||||
let mut id_map = IdMap::new();
|
let mut id_map = IdMap::new();
|
||||||
|
|
||||||
@ -318,7 +319,7 @@ fn sidebar_assoc_items<'a>(
|
|||||||
cx,
|
cx,
|
||||||
&mut deref_methods,
|
&mut deref_methods,
|
||||||
impl_,
|
impl_,
|
||||||
v,
|
v.iter().copied(),
|
||||||
&mut derefs,
|
&mut derefs,
|
||||||
&mut used_links,
|
&mut used_links,
|
||||||
);
|
);
|
||||||
@ -348,7 +349,7 @@ fn sidebar_deref_methods<'a>(
|
|||||||
cx: &'a Context<'_>,
|
cx: &'a Context<'_>,
|
||||||
out: &mut Vec<LinkBlock<'a>>,
|
out: &mut Vec<LinkBlock<'a>>,
|
||||||
impl_: &Impl,
|
impl_: &Impl,
|
||||||
v: &[Impl],
|
v: impl Iterator<Item = &'a Impl>,
|
||||||
derefs: &mut DefIdSet,
|
derefs: &mut DefIdSet,
|
||||||
used_links: &mut FxHashSet<String>,
|
used_links: &mut FxHashSet<String>,
|
||||||
) {
|
) {
|
||||||
@ -373,7 +374,7 @@ fn sidebar_deref_methods<'a>(
|
|||||||
// Avoid infinite cycles
|
// Avoid infinite cycles
|
||||||
return;
|
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
|
let inner_impl = target
|
||||||
.def_id(c)
|
.def_id(c)
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
@ -424,7 +425,7 @@ fn sidebar_deref_methods<'a>(
|
|||||||
cx,
|
cx,
|
||||||
out,
|
out,
|
||||||
target_deref_impl,
|
target_deref_impl,
|
||||||
target_impls,
|
target_impls.iter(),
|
||||||
derefs,
|
derefs,
|
||||||
used_links,
|
used_links,
|
||||||
);
|
);
|
||||||
|
@ -29,6 +29,11 @@ impl Bar for GenericStruct<u32> {}
|
|||||||
// @!has - '//h3' 'impl Bar for GenericStruct<u32> {}'
|
// @!has - '//h3' 'impl Bar for GenericStruct<u32> {}'
|
||||||
// Same goes for the `Deref` impl.
|
// Same goes for the `Deref` impl.
|
||||||
// @!has - '//h2' 'Methods from Deref<Target = u32>'
|
// @!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>;
|
pub type TypedefStruct = GenericStruct<u8>;
|
||||||
|
|
||||||
impl TypedefStruct {
|
impl TypedefStruct {
|
||||||
|
Loading…
Reference in New Issue
Block a user