Skip to content

Commit

Permalink
rustdoc: factor all-impls-for-item out into its own method
Browse files Browse the repository at this point in the history
  • Loading branch information
notriddle committed Sep 10, 2023
1 parent d882b21 commit c3e5ad4
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 78 deletions.
47 changes: 45 additions & 2 deletions src/librustdoc/html/render/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ use std::sync::mpsc::{channel, Receiver};

use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir::def_id::{DefIdMap, LOCAL_CRATE};
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
use rustc_span::def_id::DefId;
use rustc_span::edition::Edition;
use rustc_span::source_map::FileName;
use rustc_span::{sym, Symbol};
Expand All @@ -22,13 +24,13 @@ use super::{
sidebar::{sidebar_module_like, Sidebar},
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::docfs::{DocFS, PathError};
use crate::error::Error;
use crate::formats::cache::Cache;
use crate::formats::item_type::ItemType;
use crate::formats::FormatRenderer;
use crate::formats::{self, FormatRenderer};
use crate::html::escape::Escape;
use crate::html::format::{join_with_double_colon, Buffer};
use crate::html::markdown::{self, plain_text_summary, ErrorCodes, IdMap};
Expand Down Expand Up @@ -147,6 +149,47 @@ impl SharedContext<'_> {
pub(crate) fn edition(&self) -> 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 v: Vec<&formats::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 mut saw_impls = FxHashSet::default();
v.retain(|i| saw_impls.insert(i.def_id()));
v
}
}

impl<'tcx> Context<'tcx> {
Expand Down
48 changes: 8 additions & 40 deletions src/librustdoc/html/render/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir::def_id::{DefId, DefIdSet};
use rustc_hir::Mutability;
use rustc_middle::middle::stability;
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
use rustc_middle::ty::TyCtxt;
use rustc_span::{
symbol::{sym, Symbol},
Expand All @@ -63,7 +62,6 @@ use rustc_span::{
use serde::ser::{SerializeMap, SerializeSeq};
use serde::{Serialize, Serializer};

use crate::clean::types::TypeAliasItem;
use crate::clean::{self, ItemId, RenderedLink, SelfTy};
use crate::error::Error;
use crate::formats::cache::Cache;
Expand Down Expand Up @@ -1119,13 +1117,13 @@ pub(crate) fn render_all_impls(
fn render_assoc_items<'a, 'cx: 'a>(
cx: &'a mut Context<'cx>,
containing_item: &'a clean::Item,
it: DefId,
did: DefId,
what: AssocItemRender<'a>,
) -> impl fmt::Display + 'a + Captures<'cx> {
let mut derefs = DefIdSet::default();
derefs.insert(it);
derefs.insert(did);
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(())
})
}
Expand All @@ -1134,46 +1132,16 @@ fn render_assoc_items_inner(
mut w: &mut dyn fmt::Write,
cx: &mut Context<'_>,
containing_item: &clean::Item,
it: DefId,
did: DefId,
what: AssocItemRender<'_>,
derefs: &mut DefIdSet,
) {
info!("Documenting associated items of {:?}", containing_item.name);
let shared = Rc::clone(&cx.shared);
let cache = &shared.cache;
let tcx = cx.tcx();
let av = if let TypeAliasItem(ait) = &*containing_item.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(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 v = shared.all_impls_for_item(containing_item, did);
let v = v.as_slice();
let (non_trait, traits): (Vec<&Impl>, _) =
v.iter().partition(|i| i.inner_impl().trait_.is_none());
let mut saw_impls = FxHashSet::default();
if !non_trait.is_empty() {
let mut tmp_buf = Buffer::html();
Expand Down
38 changes: 2 additions & 36 deletions src/librustdoc/html/render/sidebar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@ 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},
};
Expand Down Expand Up @@ -280,40 +278,8 @@ fn sidebar_assoc_items<'a>(
links: &mut Vec<LinkBlock<'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 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 methods = Vec::new();
Expand Down

0 comments on commit c3e5ad4

Please sign in to comment.