Skip to content

Commit 030e4d3

Browse files
committed
Auto merge of #115682 - notriddle:notriddle/impl-sidebar, r=GuillaumeGomez
rustdoc: add impl items from aliased type into sidebar Follow-up of #115201.
2 parents c0583a0 + c79b960 commit 030e4d3

File tree

4 files changed

+71
-48
lines changed

4 files changed

+71
-48
lines changed

src/librustdoc/html/render/context.rs

+51-2
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@ use std::sync::mpsc::{channel, Receiver};
77

88
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
99
use rustc_hir::def_id::{DefIdMap, LOCAL_CRATE};
10+
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
1011
use rustc_middle::ty::TyCtxt;
1112
use rustc_session::Session;
13+
use rustc_span::def_id::DefId;
1214
use rustc_span::edition::Edition;
1315
use rustc_span::source_map::FileName;
1416
use rustc_span::{sym, Symbol};
@@ -22,13 +24,13 @@ use super::{
2224
sidebar::{sidebar_module_like, Sidebar},
2325
AllTypes, LinkFromSrc, StylePath,
2426
};
25-
use crate::clean::{self, types::ExternalLocation, ExternalCrate};
27+
use crate::clean::{self, types::ExternalLocation, ExternalCrate, TypeAliasItem};
2628
use crate::config::{ModuleSorting, RenderOptions};
2729
use crate::docfs::{DocFS, PathError};
2830
use crate::error::Error;
2931
use crate::formats::cache::Cache;
3032
use crate::formats::item_type::ItemType;
31-
use crate::formats::FormatRenderer;
33+
use crate::formats::{self, FormatRenderer};
3234
use crate::html::escape::Escape;
3335
use crate::html::format::{join_with_double_colon, Buffer};
3436
use crate::html::markdown::{self, plain_text_summary, ErrorCodes, IdMap};
@@ -147,6 +149,53 @@ impl SharedContext<'_> {
147149
pub(crate) fn edition(&self) -> Edition {
148150
self.tcx.sess.edition()
149151
}
152+
153+
/// Returns a list of impls on the given type, and, if it's a type alias,
154+
/// other types that it aliases.
155+
pub(crate) fn all_impls_for_item<'a>(
156+
&'a self,
157+
it: &clean::Item,
158+
did: DefId,
159+
) -> Vec<&'a formats::Impl> {
160+
let tcx = self.tcx;
161+
let cache = &self.cache;
162+
let mut saw_impls = FxHashSet::default();
163+
let mut v: Vec<&formats::Impl> = cache
164+
.impls
165+
.get(&did)
166+
.map(Vec::as_slice)
167+
.unwrap_or(&[])
168+
.iter()
169+
.filter(|i| saw_impls.insert(i.def_id()))
170+
.collect();
171+
if let TypeAliasItem(ait) = &*it.kind &&
172+
let aliased_clean_type = ait.item_type.as_ref().unwrap_or(&ait.type_) &&
173+
let Some(aliased_type_defid) = aliased_clean_type.def_id(cache) &&
174+
let Some(av) = cache.impls.get(&aliased_type_defid) &&
175+
let Some(alias_def_id) = it.item_id.as_def_id()
176+
{
177+
// This branch of the compiler compares types structually, but does
178+
// not check trait bounds. That's probably fine, since type aliases
179+
// don't normally constrain on them anyway.
180+
// https://github.com/rust-lang/rust/issues/21903
181+
//
182+
// FIXME(lazy_type_alias): Once the feature is complete or stable, rewrite this to use type unification.
183+
// Be aware of `tests/rustdoc/issue-112515-impl-ty-alias.rs` which might regress.
184+
let aliased_ty = tcx.type_of(alias_def_id).skip_binder();
185+
let reject_cx = DeepRejectCtxt {
186+
treat_obligation_params: TreatParams::AsCandidateKey,
187+
};
188+
v.extend(av.iter().filter(|impl_| {
189+
if let Some(impl_def_id) = impl_.impl_item.item_id.as_def_id() {
190+
reject_cx.types_may_unify(aliased_ty, tcx.type_of(impl_def_id).skip_binder())
191+
&& saw_impls.insert(impl_def_id)
192+
} else {
193+
false
194+
}
195+
}));
196+
}
197+
v
198+
}
150199
}
151200

152201
impl<'tcx> Context<'tcx> {

src/librustdoc/html/render/mod.rs

+8-40
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
5454
use rustc_hir::def_id::{DefId, DefIdSet};
5555
use rustc_hir::Mutability;
5656
use rustc_middle::middle::stability;
57-
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
5857
use rustc_middle::ty::TyCtxt;
5958
use rustc_span::{
6059
symbol::{sym, Symbol},
@@ -63,7 +62,6 @@ use rustc_span::{
6362
use serde::ser::{SerializeMap, SerializeSeq};
6463
use serde::{Serialize, Serializer};
6564

66-
use crate::clean::types::TypeAliasItem;
6765
use crate::clean::{self, ItemId, RenderedLink, SelfTy};
6866
use crate::error::Error;
6967
use crate::formats::cache::Cache;
@@ -1119,13 +1117,13 @@ pub(crate) fn render_all_impls(
11191117
fn render_assoc_items<'a, 'cx: 'a>(
11201118
cx: &'a mut Context<'cx>,
11211119
containing_item: &'a clean::Item,
1122-
it: DefId,
1120+
did: DefId,
11231121
what: AssocItemRender<'a>,
11241122
) -> impl fmt::Display + 'a + Captures<'cx> {
11251123
let mut derefs = DefIdSet::default();
1126-
derefs.insert(it);
1124+
derefs.insert(did);
11271125
display_fn(move |f| {
1128-
render_assoc_items_inner(f, cx, containing_item, it, what, &mut derefs);
1126+
render_assoc_items_inner(f, cx, containing_item, did, what, &mut derefs);
11291127
Ok(())
11301128
})
11311129
}
@@ -1134,46 +1132,16 @@ fn render_assoc_items_inner(
11341132
mut w: &mut dyn fmt::Write,
11351133
cx: &mut Context<'_>,
11361134
containing_item: &clean::Item,
1137-
it: DefId,
1135+
did: DefId,
11381136
what: AssocItemRender<'_>,
11391137
derefs: &mut DefIdSet,
11401138
) {
11411139
info!("Documenting associated items of {:?}", containing_item.name);
11421140
let shared = Rc::clone(&cx.shared);
1143-
let cache = &shared.cache;
1144-
let tcx = cx.tcx();
1145-
let av = if let TypeAliasItem(ait) = &*containing_item.kind &&
1146-
let aliased_clean_type = ait.item_type.as_ref().unwrap_or(&ait.type_) &&
1147-
let Some(aliased_type_defid) = aliased_clean_type.def_id(cache) &&
1148-
let Some(mut av) = cache.impls.get(&aliased_type_defid).cloned() &&
1149-
let Some(alias_def_id) = containing_item.item_id.as_def_id()
1150-
{
1151-
// This branch of the compiler compares types structually, but does
1152-
// not check trait bounds. That's probably fine, since type aliases
1153-
// don't normally constrain on them anyway.
1154-
// https://github.com/rust-lang/rust/issues/21903
1155-
//
1156-
// FIXME(lazy_type_alias): Once the feature is complete or stable, rewrite this to use type unification.
1157-
// Be aware of `tests/rustdoc/issue-112515-impl-ty-alias.rs` which might regress.
1158-
let aliased_ty = tcx.type_of(alias_def_id).skip_binder();
1159-
let reject_cx = DeepRejectCtxt {
1160-
treat_obligation_params: TreatParams::AsCandidateKey,
1161-
};
1162-
av.retain(|impl_| {
1163-
if let Some(impl_def_id) = impl_.impl_item.item_id.as_def_id() {
1164-
reject_cx.types_may_unify(aliased_ty, tcx.type_of(impl_def_id).skip_binder())
1165-
} else {
1166-
false
1167-
}
1168-
});
1169-
av
1170-
} else {
1171-
Vec::new()
1172-
};
1173-
let blank = Vec::new();
1174-
let v = cache.impls.get(&it).unwrap_or(&blank);
1175-
let (non_trait, traits): (Vec<_>, _) =
1176-
v.iter().chain(&av[..]).partition(|i| i.inner_impl().trait_.is_none());
1141+
let v = shared.all_impls_for_item(containing_item, did);
1142+
let v = v.as_slice();
1143+
let (non_trait, traits): (Vec<&Impl>, _) =
1144+
v.iter().partition(|i| i.inner_impl().trait_.is_none());
11771145
let mut saw_impls = FxHashSet::default();
11781146
if !non_trait.is_empty() {
11791147
let mut tmp_buf = Buffer::html();

src/librustdoc/html/render/sidebar.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -278,11 +278,12 @@ fn sidebar_assoc_items<'a>(
278278
links: &mut Vec<LinkBlock<'a>>,
279279
) {
280280
let did = it.item_id.expect_def_id();
281-
let cache = cx.cache();
281+
let v = cx.shared.all_impls_for_item(it, it.item_id.expect_def_id());
282+
let v = v.as_slice();
282283

283284
let mut assoc_consts = Vec::new();
284285
let mut methods = Vec::new();
285-
if let Some(v) = cache.impls.get(&did) {
286+
if !v.is_empty() {
286287
let mut used_links = FxHashSet::default();
287288
let mut id_map = IdMap::new();
288289

@@ -318,7 +319,7 @@ fn sidebar_assoc_items<'a>(
318319
cx,
319320
&mut deref_methods,
320321
impl_,
321-
v,
322+
v.iter().copied(),
322323
&mut derefs,
323324
&mut used_links,
324325
);
@@ -348,7 +349,7 @@ fn sidebar_deref_methods<'a>(
348349
cx: &'a Context<'_>,
349350
out: &mut Vec<LinkBlock<'a>>,
350351
impl_: &Impl,
351-
v: &[Impl],
352+
v: impl Iterator<Item = &'a Impl>,
352353
derefs: &mut DefIdSet,
353354
used_links: &mut FxHashSet<String>,
354355
) {
@@ -373,7 +374,7 @@ fn sidebar_deref_methods<'a>(
373374
// Avoid infinite cycles
374375
return;
375376
}
376-
let deref_mut = v.iter().any(|i| i.trait_did() == cx.tcx().lang_items().deref_mut_trait());
377+
let deref_mut = { v }.any(|i| i.trait_did() == cx.tcx().lang_items().deref_mut_trait());
377378
let inner_impl = target
378379
.def_id(c)
379380
.or_else(|| {
@@ -424,7 +425,7 @@ fn sidebar_deref_methods<'a>(
424425
cx,
425426
out,
426427
target_deref_impl,
427-
target_impls,
428+
target_impls.iter(),
428429
derefs,
429430
used_links,
430431
);

tests/rustdoc/issue-32077-type-alias-impls.rs

+5
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ impl Bar for GenericStruct<u32> {}
2929
// @!has - '//h3' 'impl Bar for GenericStruct<u32> {}'
3030
// Same goes for the `Deref` impl.
3131
// @!has - '//h2' 'Methods from Deref<Target = u32>'
32+
// @count - '//nav[@class="sidebar"]//a' 'on_alias' 1
33+
// @count - '//nav[@class="sidebar"]//a' 'on_gen' 1
34+
// @count - '//nav[@class="sidebar"]//a' 'Foo' 1
35+
// @!has - '//nav[@class="sidebar"]//a' 'Bar'
36+
// @!has - '//nav[@class="sidebar"]//a' 'on_u32'
3237
pub type TypedefStruct = GenericStruct<u8>;
3338

3439
impl TypedefStruct {

0 commit comments

Comments
 (0)