Skip to content

Commit fe6b0b8

Browse files
committed
Fill in "Implementors" section in navbar
Fixes #91118
1 parent 65f3f8b commit fe6b0b8

File tree

4 files changed

+95
-68
lines changed

4 files changed

+95
-68
lines changed

src/librustdoc/formats/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,8 @@ impl Impl {
4040
crate fn trait_did(&self) -> Option<DefId> {
4141
self.inner_impl().trait_.as_ref().map(|t| t.def_id())
4242
}
43+
44+
crate fn is_local(&self, cache: &cache::Cache) -> bool {
45+
self.inner_impl().for_.def_id(cache).map_or(true, |d| cache.paths.contains_key(&d))
46+
}
4347
}

src/librustdoc/html/render/context.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ crate struct Context<'tcx> {
5959
pub(super) deref_id_map: RefCell<FxHashMap<DefId, String>>,
6060
/// The map used to ensure all generated 'id=' attributes are unique.
6161
pub(super) id_map: RefCell<IdMap>,
62+
/// Converts the rustc id of an item to the html id so we can link to it
63+
pub(super) item_to_html_id_map: RefCell<FxHashMap<clean::ItemId, String>>,
6264
/// Shared mutable state.
6365
///
6466
/// Issue for improving the situation: [#82381][]
@@ -73,7 +75,7 @@ crate struct Context<'tcx> {
7375

7476
// `Context` is cloned a lot, so we don't want the size to grow unexpectedly.
7577
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
76-
rustc_data_structures::static_assert_size!(Context<'_>, 144);
78+
rustc_data_structures::static_assert_size!(Context<'_>, 184);
7779

7880
/// Shared mutable state used in [`Context`] and elsewhere.
7981
crate struct SharedContext<'tcx> {
@@ -517,6 +519,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
517519
render_redirect_pages: false,
518520
id_map: RefCell::new(id_map),
519521
deref_id_map: RefCell::new(FxHashMap::default()),
522+
item_to_html_id_map: RefCell::new(FxHashMap::default()),
520523
shared: Rc::new(scx),
521524
include_sources,
522525
};
@@ -541,6 +544,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
541544
dst: self.dst.clone(),
542545
render_redirect_pages: self.render_redirect_pages,
543546
deref_id_map: RefCell::new(FxHashMap::default()),
547+
item_to_html_id_map: RefCell::new(FxHashMap::default()),
544548
id_map: RefCell::new(IdMap::new()),
545549
shared: Rc::clone(&self.shared),
546550
include_sources: self.include_sources,

src/librustdoc/html/render/mod.rs

Lines changed: 84 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1613,6 +1613,7 @@ fn render_impl(
16131613
);
16141614
write!(w, "<summary>")
16151615
}
1616+
16161617
render_impl_summary(
16171618
w,
16181619
cx,
@@ -1691,7 +1692,7 @@ pub(crate) fn render_impl_summary(
16911692
// in documentation pages for trait with automatic implementations like "Send" and "Sync".
16921693
aliases: &[String],
16931694
) {
1694-
let id = cx.derive_id(match i.inner_impl().trait_ {
1695+
let html_id = cx.derive_id(match i.inner_impl().trait_ {
16951696
Some(ref t) => {
16961697
if is_on_foreign_type {
16971698
get_id_for_impl_on_foreign_type(&i.inner_impl().for_, t, cx)
@@ -1701,14 +1702,17 @@ pub(crate) fn render_impl_summary(
17011702
}
17021703
None => "impl".to_string(),
17031704
});
1705+
1706+
cx.item_to_html_id_map.borrow_mut().insert(i.impl_item.def_id, html_id.clone());
1707+
17041708
let aliases = if aliases.is_empty() {
17051709
String::new()
17061710
} else {
17071711
format!(" data-aliases=\"{}\"", aliases.join(","))
17081712
};
1709-
write!(w, "<div id=\"{}\" class=\"impl has-srclink\"{}>", id, aliases);
1713+
write!(w, "<div id=\"{}\" class=\"impl has-srclink\"{}>", html_id, aliases);
17101714
render_rightside(w, cx, &i.impl_item, containing_item);
1711-
write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", id);
1715+
write!(w, "<a href=\"#{}\" class=\"anchor\"></a>", html_id);
17121716
write!(w, "<h3 class=\"code-header in-band\">");
17131717

17141718
if let Some(use_absolute) = use_absolute {
@@ -2214,20 +2218,12 @@ fn get_id_for_impl_on_foreign_type(
22142218
small_url_encode(format!("impl-{:#}-for-{:#}", trait_.print(cx), for_.print(cx)))
22152219
}
22162220

2217-
fn extract_for_impl_name(item: &clean::Item, cx: &Context<'_>) -> Option<(String, String)> {
2218-
match *item.kind {
2219-
clean::ItemKind::ImplItem(ref i) => {
2220-
i.trait_.as_ref().map(|trait_| {
2221-
// Alternative format produces no URLs,
2222-
// so this parameter does nothing.
2223-
(
2224-
format!("{:#}", i.for_.print(cx)),
2225-
get_id_for_impl_on_foreign_type(&i.for_, trait_, cx),
2226-
)
2227-
})
2228-
}
2229-
_ => None,
2230-
}
2221+
fn extract_for_impl_name(item: &Impl, cx: &Context<'_>) -> (String, String) {
2222+
let i = item.inner_impl();
2223+
let trait_ = i.trait_.as_ref().unwrap();
2224+
// Alternative format produces no URLs,
2225+
// so this parameter does nothing.
2226+
(format!("{:#}", i.for_.print(cx)), get_id_for_impl_on_foreign_type(&i.for_, trait_, cx))
22312227
}
22322228

22332229
fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) {
@@ -2236,101 +2232,125 @@ fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean
22362232
fn print_sidebar_section(
22372233
out: &mut Buffer,
22382234
items: &[clean::Item],
2239-
before: &str,
2235+
title: &str,
2236+
id: &str,
22402237
filter: impl Fn(&clean::Item) -> bool,
22412238
write: impl Fn(&mut Buffer, &str),
2242-
after: &str,
22432239
) {
2244-
let mut items = items
2245-
.iter()
2246-
.filter_map(|m| match m.name {
2247-
Some(ref name) if filter(m) => Some(name.as_str()),
2248-
_ => None,
2249-
})
2250-
.collect::<Vec<_>>();
2240+
print_sidebar_section_with(
2241+
out,
2242+
title,
2243+
id,
2244+
items.iter().filter(|i| filter(i)).filter_map(|i| i.name.map(|n| n.as_str())),
2245+
|buf, s| write(buf, &s),
2246+
)
2247+
}
2248+
2249+
fn print_sidebar_section_with<T: Ord>(
2250+
out: &mut Buffer,
2251+
title: &str,
2252+
id: &str,
2253+
iter: impl Iterator<Item = T>,
2254+
write: impl Fn(&mut Buffer, T),
2255+
) {
2256+
let mut items = iter.collect::<Vec<_>>();
22512257

22522258
if !items.is_empty() {
22532259
items.sort_unstable();
2254-
out.push_str(before);
2260+
write!(
2261+
out,
2262+
"<h3 class=\"sidebar-title\"><a href=\"#{}\">\
2263+
{}</a></h3><div class=\"sidebar-links\">",
2264+
id, title
2265+
);
22552266
for item in items.into_iter() {
2256-
write(out, &item);
2267+
write(out, item);
22572268
}
2258-
out.push_str(after);
2269+
out.push_str("</div>");
22592270
}
22602271
}
22612272

22622273
print_sidebar_section(
22632274
buf,
22642275
&t.items,
2265-
"<h3 class=\"sidebar-title\"><a href=\"#associated-types\">\
2266-
Associated Types</a></h3><div class=\"sidebar-links\">",
2276+
"Associated Types",
2277+
"associated-types",
22672278
|m| m.is_associated_type(),
22682279
|out, sym| write!(out, "<a href=\"#associatedtype.{0}\">{0}</a>", sym),
2269-
"</div>",
22702280
);
22712281

22722282
print_sidebar_section(
22732283
buf,
22742284
&t.items,
2275-
"<h3 class=\"sidebar-title\"><a href=\"#associated-const\">\
2276-
Associated Constants</a></h3><div class=\"sidebar-links\">",
2285+
"Associated Constants",
2286+
"associated-const",
22772287
|m| m.is_associated_const(),
22782288
|out, sym| write!(out, "<a href=\"#associatedconstant.{0}\">{0}</a>", sym),
2279-
"</div>",
22802289
);
22812290

22822291
print_sidebar_section(
22832292
buf,
22842293
&t.items,
2285-
"<h3 class=\"sidebar-title\"><a href=\"#required-methods\">\
2286-
Required Methods</a></h3><div class=\"sidebar-links\">",
2294+
"Required Methods",
2295+
"required-methods",
22872296
|m| m.is_ty_method(),
22882297
|out, sym| write!(out, "<a href=\"#tymethod.{0}\">{0}</a>", sym),
2289-
"</div>",
22902298
);
22912299

22922300
print_sidebar_section(
22932301
buf,
22942302
&t.items,
2295-
"<h3 class=\"sidebar-title\"><a href=\"#provided-methods\">\
2296-
Provided Methods</a></h3><div class=\"sidebar-links\">",
2303+
"Provided Methods",
2304+
"provided-methods",
22972305
|m| m.is_method(),
22982306
|out, sym| write!(out, "<a href=\"#method.{0}\">{0}</a>", sym),
2299-
"</div>",
23002307
);
23012308

23022309
let cache = cx.cache();
2303-
if let Some(implementors) = cache.implementors.get(&it.def_id.expect_def_id()) {
2304-
let mut res = implementors
2305-
.iter()
2306-
.filter(|i| {
2307-
i.inner_impl().for_.def_id(cache).map_or(false, |d| !cache.paths.contains_key(&d))
2308-
})
2309-
.filter_map(|i| extract_for_impl_name(&i.impl_item, cx))
2310-
.collect::<Vec<_>>();
2311-
2312-
if !res.is_empty() {
2313-
res.sort();
2314-
buf.push_str(
2315-
"<h3 class=\"sidebar-title\"><a href=\"#foreign-impls\">\
2316-
Implementations on Foreign Types</a></h3>\
2317-
<div class=\"sidebar-links\">",
2318-
);
2319-
for (name, id) in res.into_iter() {
2320-
write!(buf, "<a href=\"#{}\">{}</a>", id, Escape(&name));
2321-
}
2322-
buf.push_str("</div>");
2323-
}
2324-
}
2310+
let did = it.def_id.expect_def_id();
2311+
2312+
let (local_impl, foreign_impls) = cache
2313+
.implementors
2314+
.get(&did)
2315+
.iter()
2316+
.flat_map(|x| *x)
2317+
.partition::<Vec<_>, _>(|i| i.is_local(cache));
2318+
2319+
print_sidebar_section_with(
2320+
buf,
2321+
"Implementations on Foreign Types",
2322+
"foreign-impls",
2323+
foreign_impls.iter().map(|i| extract_for_impl_name(i, cx)),
2324+
|buf, (name, id)| write!(buf, "<a href=\"#{}\">{}</a>", id, Escape(&name)),
2325+
);
23252326

23262327
sidebar_assoc_items(cx, buf, it);
23272328

2328-
buf.push_str("<h3 class=\"sidebar-title\"><a href=\"#implementors\">Implementors</a></h3>");
2329+
print_sidebar_section_with(
2330+
buf,
2331+
"Implementors",
2332+
"implementors",
2333+
local_impl.iter().filter(|i| i.inner_impl().polarity == ty::ImplPolarity::Positive).map(
2334+
|i| {
2335+
(
2336+
format!("{:#}", i.inner_impl().for_.print(cx)),
2337+
cx.item_to_html_id_map
2338+
.borrow()
2339+
.get(&i.impl_item.def_id)
2340+
.unwrap_or_else(|| panic!("Not in index {:#?}", i))
2341+
.clone(),
2342+
)
2343+
},
2344+
),
2345+
|buf, (name, id)| write!(buf, "<a href=\"#{}\">{}</a>", id, Escape(&name)),
2346+
);
2347+
23292348
if t.is_auto {
23302349
buf.push_str(
23312350
"<h3 class=\"sidebar-title\"><a \
23322351
href=\"#synthetic-implementors\">Auto Implementors</a></h3>",
23332352
);
2353+
// FIXME: List Auto Implementors
23342354
}
23352355

23362356
buf.push_str("</div>")

src/librustdoc/html/render/print_item.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -741,9 +741,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
741741
}
742742
}
743743

744-
let (local, foreign) = implementors.iter().partition::<Vec<_>, _>(|i| {
745-
i.inner_impl().for_.def_id(cache).map_or(true, |d| cache.paths.contains_key(&d))
746-
});
744+
let (local, foreign) = implementors.iter().partition::<Vec<_>, _>(|i| i.is_local(cache));
747745

748746
let (mut synthetic, mut concrete): (Vec<&&Impl>, Vec<&&Impl>) =
749747
local.iter().partition(|i| i.inner_impl().kind.is_auto());
@@ -784,6 +782,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
784782
"Implementors",
785783
"<div class=\"item-list\" id=\"implementors-list\">",
786784
);
785+
787786
for implementor in concrete {
788787
render_implementor(cx, implementor, it, w, &implementor_dups, &[]);
789788
}

0 commit comments

Comments
 (0)