Skip to content

Commit 775e969

Browse files
authored
Rollup merge of #90946 - GuillaumeGomez:def-id-remove-weird-case, r=Manishearth
Ignore `reference`s in "Type::inner_def_id" Fixes #90775. Reopening of #90726. As discussed on [zulip](https://rust-lang.zulipchat.com/#narrow/stream/266220-rustdoc/topic/rendering.20for.20reference.20primitive.20doc.20page), the reference page shouldn't list these implementations (since they are listed on the types and on the traits in any case). And more generally, you don't implement something on a reference but on something behind a reference. I think it's the important point. So currently it looks like this: ![Screenshot from 2021-11-16 10-20-41](https://user-images.githubusercontent.com/3050060/141957799-57aeadc5-41f8-45f6-a4a5-33b1eca6a500.png) With this PR, only the implementations over generics behind a reference are kept. You can test it [here](https://rustdoc.crud.net/imperio/def-id-remove-weird-case/std/primitive.reference.html). cc ``@camelid``
2 parents 12e4fd0 + 477b7ba commit 775e969

File tree

3 files changed

+219
-118
lines changed

3 files changed

+219
-118
lines changed

src/librustdoc/html/render/mod.rs

Lines changed: 167 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -613,10 +613,10 @@ fn short_item_info(
613613

614614
// Render the list of items inside one of the sections "Trait Implementations",
615615
// "Auto Trait Implementations," "Blanket Trait Implementations" (on struct/enum pages).
616-
fn render_impls(
616+
pub(crate) fn render_impls(
617617
cx: &mut Context<'_>,
618618
w: &mut Buffer,
619-
impls: &[&&Impl],
619+
impls: &[&Impl],
620620
containing_item: &clean::Item,
621621
toggle_open_by_default: bool,
622622
) {
@@ -1025,6 +1025,47 @@ impl<'a> AssocItemLink<'a> {
10251025
}
10261026
}
10271027

1028+
fn write_impl_section_heading(w: &mut Buffer, title: &str, id: &str) {
1029+
write!(
1030+
w,
1031+
"<h2 id=\"{id}\" class=\"small-section-header\">\
1032+
{title}\
1033+
<a href=\"#{id}\" class=\"anchor\"></a>\
1034+
</h2>"
1035+
);
1036+
}
1037+
1038+
pub(crate) fn render_all_impls(
1039+
w: &mut Buffer,
1040+
cx: &mut Context<'_>,
1041+
containing_item: &clean::Item,
1042+
concrete: &[&Impl],
1043+
synthetic: &[&Impl],
1044+
blanket_impl: &[&Impl],
1045+
) {
1046+
let mut impls = Buffer::empty_from(w);
1047+
render_impls(cx, &mut impls, concrete, containing_item, true);
1048+
let impls = impls.into_inner();
1049+
if !impls.is_empty() {
1050+
write_impl_section_heading(w, "Trait Implementations", "trait-implementations");
1051+
write!(w, "<div id=\"trait-implementations-list\">{}</div>", impls);
1052+
}
1053+
1054+
if !synthetic.is_empty() {
1055+
write_impl_section_heading(w, "Auto Trait Implementations", "synthetic-implementations");
1056+
w.write_str("<div id=\"synthetic-implementations-list\">");
1057+
render_impls(cx, w, synthetic, containing_item, false);
1058+
w.write_str("</div>");
1059+
}
1060+
1061+
if !blanket_impl.is_empty() {
1062+
write_impl_section_heading(w, "Blanket Implementations", "blanket-implementations");
1063+
w.write_str("<div id=\"blanket-implementations-list\">");
1064+
render_impls(cx, w, blanket_impl, containing_item, false);
1065+
w.write_str("</div>");
1066+
}
1067+
}
1068+
10281069
fn render_assoc_items(
10291070
w: &mut Buffer,
10301071
cx: &mut Context<'_>,
@@ -1054,12 +1095,7 @@ fn render_assoc_items_inner(
10541095
let mut tmp_buf = Buffer::empty_from(w);
10551096
let (render_mode, id) = match what {
10561097
AssocItemRender::All => {
1057-
tmp_buf.write_str(
1058-
"<h2 id=\"implementations\" class=\"small-section-header\">\
1059-
Implementations\
1060-
<a href=\"#implementations\" class=\"anchor\"></a>\
1061-
</h2>",
1062-
);
1098+
write_impl_section_heading(&mut tmp_buf, "Implementations", "implementations");
10631099
(RenderMode::Normal, "implementations-list".to_owned())
10641100
}
10651101
AssocItemRender::DerefFor { trait_, type_, deref_mut_ } => {
@@ -1068,15 +1104,14 @@ fn render_assoc_items_inner(
10681104
if let Some(def_id) = type_.def_id(cx.cache()) {
10691105
cx.deref_id_map.insert(def_id, id.clone());
10701106
}
1071-
write!(
1072-
tmp_buf,
1073-
"<h2 id=\"{id}\" class=\"small-section-header\">\
1074-
<span>Methods from {trait_}&lt;Target = {type_}&gt;</span>\
1075-
<a href=\"#{id}\" class=\"anchor\"></a>\
1076-
</h2>",
1077-
id = id,
1078-
trait_ = trait_.print(cx),
1079-
type_ = type_.print(cx),
1107+
write_impl_section_heading(
1108+
&mut tmp_buf,
1109+
&format!(
1110+
"<span>Methods from {trait_}&lt;Target = {type_}&gt;</span>",
1111+
trait_ = trait_.print(cx),
1112+
type_ = type_.print(cx),
1113+
),
1114+
&id,
10801115
);
10811116
(RenderMode::ForDeref { mut_: deref_mut_ }, cx.derive_id(id))
10821117
}
@@ -1123,49 +1158,12 @@ fn render_assoc_items_inner(
11231158
return;
11241159
}
11251160

1126-
let (synthetic, concrete): (Vec<&&Impl>, Vec<&&Impl>) =
1127-
traits.iter().partition(|t| t.inner_impl().kind.is_auto());
1128-
let (blanket_impl, concrete): (Vec<&&Impl>, _) =
1161+
let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) =
1162+
traits.into_iter().partition(|t| t.inner_impl().kind.is_auto());
1163+
let (blanket_impl, concrete): (Vec<&Impl>, _) =
11291164
concrete.into_iter().partition(|t| t.inner_impl().kind.is_blanket());
11301165

1131-
let mut impls = Buffer::empty_from(w);
1132-
render_impls(cx, &mut impls, &concrete, containing_item, true);
1133-
let impls = impls.into_inner();
1134-
if !impls.is_empty() {
1135-
write!(
1136-
w,
1137-
"<h2 id=\"trait-implementations\" class=\"small-section-header\">\
1138-
Trait Implementations\
1139-
<a href=\"#trait-implementations\" class=\"anchor\"></a>\
1140-
</h2>\
1141-
<div id=\"trait-implementations-list\">{}</div>",
1142-
impls
1143-
);
1144-
}
1145-
1146-
if !synthetic.is_empty() {
1147-
w.write_str(
1148-
"<h2 id=\"synthetic-implementations\" class=\"small-section-header\">\
1149-
Auto Trait Implementations\
1150-
<a href=\"#synthetic-implementations\" class=\"anchor\"></a>\
1151-
</h2>\
1152-
<div id=\"synthetic-implementations-list\">",
1153-
);
1154-
render_impls(cx, w, &synthetic, containing_item, false);
1155-
w.write_str("</div>");
1156-
}
1157-
1158-
if !blanket_impl.is_empty() {
1159-
w.write_str(
1160-
"<h2 id=\"blanket-implementations\" class=\"small-section-header\">\
1161-
Blanket Implementations\
1162-
<a href=\"#blanket-implementations\" class=\"anchor\"></a>\
1163-
</h2>\
1164-
<div id=\"blanket-implementations-list\">",
1165-
);
1166-
render_impls(cx, w, &blanket_impl, containing_item, false);
1167-
w.write_str("</div>");
1168-
}
1166+
render_all_impls(w, cx, containing_item, &concrete, &synthetic, &blanket_impl);
11691167
}
11701168
}
11711169

@@ -1970,6 +1968,70 @@ fn small_url_encode(s: String) -> String {
19701968
}
19711969
}
19721970

1971+
pub(crate) fn sidebar_render_assoc_items(
1972+
cx: &Context<'_>,
1973+
out: &mut Buffer,
1974+
id_map: &mut IdMap,
1975+
concrete: Vec<&Impl>,
1976+
synthetic: Vec<&Impl>,
1977+
blanket_impl: Vec<&Impl>,
1978+
) {
1979+
let format_impls = |impls: Vec<&Impl>, id_map: &mut IdMap| {
1980+
let mut links = FxHashSet::default();
1981+
1982+
let mut ret = impls
1983+
.iter()
1984+
.filter_map(|it| {
1985+
let trait_ = it.inner_impl().trait_.as_ref()?;
1986+
let encoded =
1987+
id_map.derive(get_id_for_impl(&it.inner_impl().for_, Some(trait_), cx));
1988+
1989+
let i_display = format!("{:#}", trait_.print(cx));
1990+
let out = Escape(&i_display);
1991+
let prefix = match it.inner_impl().polarity {
1992+
ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "",
1993+
ty::ImplPolarity::Negative => "!",
1994+
};
1995+
let generated = format!("<a href=\"#{}\">{}{}</a>", encoded, prefix, out);
1996+
if links.insert(generated.clone()) { Some(generated) } else { None }
1997+
})
1998+
.collect::<Vec<String>>();
1999+
ret.sort();
2000+
ret
2001+
};
2002+
2003+
let concrete_format = format_impls(concrete, id_map);
2004+
let synthetic_format = format_impls(synthetic, id_map);
2005+
let blanket_format = format_impls(blanket_impl, id_map);
2006+
2007+
if !concrete_format.is_empty() {
2008+
print_sidebar_block(
2009+
out,
2010+
"trait-implementations",
2011+
"Trait Implementations",
2012+
concrete_format.iter(),
2013+
);
2014+
}
2015+
2016+
if !synthetic_format.is_empty() {
2017+
print_sidebar_block(
2018+
out,
2019+
"synthetic-implementations",
2020+
"Auto Trait Implementations",
2021+
synthetic_format.iter(),
2022+
);
2023+
}
2024+
2025+
if !blanket_format.is_empty() {
2026+
print_sidebar_block(
2027+
out,
2028+
"blanket-implementations",
2029+
"Blanket Implementations",
2030+
blanket_format.iter(),
2031+
);
2032+
}
2033+
}
2034+
19732035
fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
19742036
let did = it.item_id.expect_def_id();
19752037
let cache = cx.cache();
@@ -2018,65 +2080,12 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
20182080
sidebar_deref_methods(cx, out, impl_, v, &mut derefs, &mut used_links);
20192081
}
20202082

2021-
let format_impls = |impls: Vec<&Impl>, id_map: &mut IdMap| {
2022-
let mut links = FxHashSet::default();
2023-
2024-
let mut ret = impls
2025-
.iter()
2026-
.filter_map(|it| {
2027-
let trait_ = it.inner_impl().trait_.as_ref()?;
2028-
let encoded =
2029-
id_map.derive(get_id_for_impl(&it.inner_impl().for_, Some(trait_), cx));
2030-
2031-
let i_display = format!("{:#}", trait_.print(cx));
2032-
let out = Escape(&i_display);
2033-
let prefix = match it.inner_impl().polarity {
2034-
ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => "",
2035-
ty::ImplPolarity::Negative => "!",
2036-
};
2037-
let generated = format!("<a href=\"#{}\">{}{}</a>", encoded, prefix, out);
2038-
if links.insert(generated.clone()) { Some(generated) } else { None }
2039-
})
2040-
.collect::<Vec<String>>();
2041-
ret.sort();
2042-
ret
2043-
};
2044-
20452083
let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) =
20462084
v.iter().partition::<Vec<_>, _>(|i| i.inner_impl().kind.is_auto());
20472085
let (blanket_impl, concrete): (Vec<&Impl>, Vec<&Impl>) =
20482086
concrete.into_iter().partition::<Vec<_>, _>(|i| i.inner_impl().kind.is_blanket());
20492087

2050-
let concrete_format = format_impls(concrete, &mut id_map);
2051-
let synthetic_format = format_impls(synthetic, &mut id_map);
2052-
let blanket_format = format_impls(blanket_impl, &mut id_map);
2053-
2054-
if !concrete_format.is_empty() {
2055-
print_sidebar_block(
2056-
out,
2057-
"trait-implementations",
2058-
"Trait Implementations",
2059-
concrete_format.iter(),
2060-
);
2061-
}
2062-
2063-
if !synthetic_format.is_empty() {
2064-
print_sidebar_block(
2065-
out,
2066-
"synthetic-implementations",
2067-
"Auto Trait Implementations",
2068-
synthetic_format.iter(),
2069-
);
2070-
}
2071-
2072-
if !blanket_format.is_empty() {
2073-
print_sidebar_block(
2074-
out,
2075-
"blanket-implementations",
2076-
"Blanket Implementations",
2077-
blanket_format.iter(),
2078-
);
2079-
}
2088+
sidebar_render_assoc_items(cx, out, &mut id_map, concrete, synthetic, blanket_impl);
20802089
}
20812090
}
20822091
}
@@ -2346,9 +2355,54 @@ fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean
23462355
buf.push_str("</section>")
23472356
}
23482357

2358+
/// Returns the list of implementations for the primitive reference type, filtering out any
2359+
/// implementations that are on concrete or partially generic types, only keeping implementations
2360+
/// of the form `impl<T> Trait for &T`.
2361+
pub(crate) fn get_filtered_impls_for_reference<'a>(
2362+
shared: &'a Rc<SharedContext<'_>>,
2363+
it: &clean::Item,
2364+
) -> (Vec<&'a Impl>, Vec<&'a Impl>, Vec<&'a Impl>) {
2365+
let def_id = it.item_id.expect_def_id();
2366+
// If the reference primitive is somehow not defined, exit early.
2367+
let Some(v) = shared.cache.impls.get(&def_id) else { return (Vec::new(), Vec::new(), Vec::new()) };
2368+
// Since there is no "direct implementation" on the reference primitive type, we filter out
2369+
// every implementation which isn't a trait implementation.
2370+
let traits: Vec<_> = v.iter().filter(|i| i.inner_impl().trait_.is_some()).collect();
2371+
let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) =
2372+
traits.into_iter().partition(|t| t.inner_impl().kind.is_auto());
2373+
2374+
let (blanket_impl, concrete): (Vec<&Impl>, _) =
2375+
concrete.into_iter().partition(|t| t.inner_impl().kind.is_blanket());
2376+
// Now we keep only references over full generic types.
2377+
let concrete: Vec<_> = concrete
2378+
.into_iter()
2379+
.filter(|t| match t.inner_impl().for_ {
2380+
clean::Type::BorrowedRef { ref type_, .. } => type_.is_full_generic(),
2381+
_ => false,
2382+
})
2383+
.collect();
2384+
2385+
(concrete, synthetic, blanket_impl)
2386+
}
2387+
23492388
fn sidebar_primitive(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item) {
23502389
let mut sidebar = Buffer::new();
2351-
sidebar_assoc_items(cx, &mut sidebar, it);
2390+
2391+
if it.name.map(|n| n.as_str() != "reference").unwrap_or(false) {
2392+
sidebar_assoc_items(cx, &mut sidebar, it);
2393+
} else {
2394+
let shared = Rc::clone(&cx.shared);
2395+
let (concrete, synthetic, blanket_impl) = get_filtered_impls_for_reference(&shared, it);
2396+
2397+
sidebar_render_assoc_items(
2398+
cx,
2399+
&mut sidebar,
2400+
&mut IdMap::new(),
2401+
concrete,
2402+
synthetic,
2403+
blanket_impl,
2404+
);
2405+
}
23522406

23532407
if !sidebar.is_empty() {
23542408
write!(buf, "<section>{}</section>", sidebar.into_inner());

src/librustdoc/html/render/print_item.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ use std::fmt;
1616
use std::rc::Rc;
1717

1818
use super::{
19-
collect_paths_for_type, document, ensure_trailing_slash, item_ty_to_section,
20-
notable_traits_decl, render_assoc_item, render_assoc_items, render_attributes_in_code,
21-
render_attributes_in_pre, render_impl, render_rightside, render_stability_since_raw,
22-
AssocItemLink, Context, ImplRenderingParameters,
19+
collect_paths_for_type, document, ensure_trailing_slash, get_filtered_impls_for_reference,
20+
item_ty_to_section, notable_traits_decl, render_all_impls, render_assoc_item,
21+
render_assoc_items, render_attributes_in_code, render_attributes_in_pre, render_impl,
22+
render_rightside, render_stability_since_raw, AssocItemLink, Context, ImplRenderingParameters,
2323
};
2424
use crate::clean;
2525
use crate::config::ModuleSorting;
@@ -1371,8 +1371,18 @@ fn item_proc_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, m: &c
13711371
}
13721372

13731373
fn item_primitive(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
1374+
let def_id = it.item_id.expect_def_id();
13741375
document(w, cx, it, None, HeadingOffset::H2);
1375-
render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All)
1376+
if it.name.map(|n| n.as_str() != "reference").unwrap_or(false) {
1377+
render_assoc_items(w, cx, it, def_id, AssocItemRender::All);
1378+
} else {
1379+
// We handle the "reference" primitive type on its own because we only want to list
1380+
// implementations on generic types.
1381+
let shared = Rc::clone(&cx.shared);
1382+
let (concrete, synthetic, blanket_impl) = get_filtered_impls_for_reference(&shared, it);
1383+
1384+
render_all_impls(w, cx, it, &concrete, &synthetic, &blanket_impl);
1385+
}
13761386
}
13771387

13781388
fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &clean::Constant) {

0 commit comments

Comments
 (0)