Skip to content
/ rust Public
forked from rust-lang/rust

Commit 5e09019

Browse files
authored
Rollup merge of rust-lang#157540 - yotamofek:pr/rustdoc/render_all_impls-cleanup, r=GuillaumeGomez
Cleanup and optimize `render_impls` - take ownership of the `Vec<&Impl>` instead of copying into another alloc - reuse `ImplString` to do natural sort ordering - lazy formatting Somewhat of a follow-up to rust-lang#157233 and rust-lang#157179 (cc @nnethercote - thanks!) This kinda undoes rust-lang@f7c8bc2 but IMHO it makes more sense to be explicit about negative impl ordering, and also seems kinda wasteful to "render" the negativity into a string and rely on however ASCII decided to order characters. I can also undo this part, I think this PR is still a positive change even without it. r? @GuillaumeGomez LLM disclosure: I used LLM for reviewing my changes and making sure some assumptions I was making were correct (i.e. that `render_impls` will not render anything IFF the list of traits passed to it is empty)
2 parents b5fcf78 + 0053d76 commit 5e09019

3 files changed

Lines changed: 77 additions & 79 deletions

File tree

src/librustdoc/html/render/mod.rs

Lines changed: 53 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ mod type_layout;
4040
mod write_shared;
4141

4242
use std::borrow::Cow;
43+
use std::cmp::Ordering;
4344
use std::collections::VecDeque;
4445
use std::fmt::{self, Display as _, Write};
4546
use std::iter::Peekable;
@@ -79,7 +80,7 @@ use crate::html::format::{
7980
use crate::html::markdown::{
8081
HeadingOffset, IdMap, Markdown, MarkdownItemInfo, MarkdownSummaryLine, short_markdown_summary,
8182
};
82-
use crate::html::render::print_item::compare_names;
83+
use crate::html::render::print_item::ImplString;
8384
use crate::html::render::search_index::get_function_type_for_search;
8485
use crate::html::static_files::SCRAPE_EXAMPLES_HELP_MD;
8586
use crate::html::{highlight, sources};
@@ -954,46 +955,50 @@ fn impl_trait_key(cx: &Context<'_>, i: &Impl) -> Option<String> {
954955

955956
// Render the list of items inside one of the sections "Trait Implementations",
956957
// "Auto Trait Implementations," "Blanket Trait Implementations" (on struct/enum pages).
957-
fn render_impls(
958-
cx: &Context<'_>,
959-
mut w: impl Write,
960-
impls: &[&Impl],
961-
containing_item: &clean::Item,
958+
fn render_impls<'a, 'cx>(
959+
cx: &'a Context<'cx>,
960+
mut impls: Vec<&'a Impl>,
961+
containing_item: &'a clean::Item,
962962
toggle_open_by_default: bool,
963-
) -> fmt::Result {
963+
) -> impl fmt::Display + use<'a, 'cx> {
964+
impls.sort_by_cached_key(|imp| {
965+
let prefix = match imp.inner_impl().polarity {
966+
ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => Ordering::Greater,
967+
ty::ImplPolarity::Negative => Ordering::Less,
968+
};
969+
(prefix, ImplString::new_path(imp, cx))
970+
});
964971
// Render each impl alongside its `impl_trait_key`, which is used as the primary sorting key
965972
// to match the impl order in the sidebar.
966-
let mut keyed_rendered_impls = impls
967-
.iter()
968-
.map(|i| {
969-
let did = i.trait_did().unwrap();
970-
let provided_trait_methods = i.inner_impl().provided_trait_methods(cx.tcx());
971-
let assoc_link = AssocItemLink::GotoSource(did.into(), &provided_trait_methods);
972-
let imp = render_impl(
973-
cx,
974-
i,
975-
containing_item,
976-
assoc_link,
977-
RenderMode::Normal,
978-
None,
979-
&[],
980-
ImplRenderingParameters {
981-
show_def_docs: true,
982-
show_default_items: true,
983-
show_non_assoc_items: true,
984-
toggle_open_by_default,
985-
},
986-
);
987-
(impl_trait_key(cx, i).unwrap(), imp.to_string())
988-
})
989-
.collect::<Vec<_>>();
990973

991-
// Sort and then remove the `impl_trait_key`s, which are no longer needed after sorting.
992-
keyed_rendered_impls
993-
.sort_by(|(k1, h1), (k2, h2)| compare_names(k1, k2).then_with(|| h1.cmp(h2)));
994-
let joined: String = keyed_rendered_impls.into_iter().map(|a| a.1).collect();
995-
996-
w.write_str(&joined)
974+
fmt::from_fn(move |f| {
975+
impls
976+
.iter()
977+
.map(|i| {
978+
fmt::from_fn(|f| {
979+
let did = i.trait_did().unwrap();
980+
let provided_trait_methods = i.inner_impl().provided_trait_methods(cx.tcx());
981+
let assoc_link = AssocItemLink::GotoSource(did.into(), &provided_trait_methods);
982+
render_impl(
983+
cx,
984+
i,
985+
containing_item,
986+
assoc_link,
987+
RenderMode::Normal,
988+
None,
989+
&[],
990+
ImplRenderingParameters {
991+
show_def_docs: true,
992+
show_default_items: true,
993+
show_non_assoc_items: true,
994+
toggle_open_by_default,
995+
},
996+
)
997+
.fmt(f)
998+
})
999+
})
1000+
.joined("", f)
1001+
})
9971002
}
9981003

9991004
/// Build a (possibly empty) `href` attribute (a key-value pair) for the given associated item.
@@ -1415,16 +1420,12 @@ fn render_all_impls(
14151420
mut w: impl Write,
14161421
cx: &Context<'_>,
14171422
containing_item: &clean::Item,
1418-
concrete_impls: &[&Impl],
1419-
auto_trait_impls: &[&Impl],
1420-
blanket_impls: &[&Impl],
1423+
concrete_impls: Vec<&Impl>,
1424+
auto_trait_impls: Vec<&Impl>,
1425+
blanket_impls: Vec<&Impl>,
14211426
) -> fmt::Result {
1422-
let impls = {
1423-
let mut buf = String::new();
1424-
render_impls(cx, &mut buf, concrete_impls, containing_item, true)?;
1425-
buf
1426-
};
1427-
if !impls.is_empty() {
1427+
if !concrete_impls.is_empty() {
1428+
let impls = render_impls(cx, concrete_impls, containing_item, true);
14281429
write!(
14291430
w,
14301431
"{}<div id=\"trait-implementations-list\">{impls}</div>",
@@ -1433,25 +1434,24 @@ fn render_all_impls(
14331434
}
14341435

14351436
if !auto_trait_impls.is_empty() {
1437+
let impls = render_impls(cx, auto_trait_impls, containing_item, false);
14361438
// FIXME: Change the ID to `auto-trait-implementations-list`!
14371439
write!(
14381440
w,
1439-
"{}<div id=\"synthetic-implementations-list\">",
1441+
"{}<div id=\"synthetic-implementations-list\">{impls}</div>",
14401442
write_impl_section_heading("Auto Trait Implementations", "synthetic-implementations",)
14411443
)?;
1442-
render_impls(cx, &mut w, auto_trait_impls, containing_item, false)?;
1443-
w.write_str("</div>")?;
14441444
}
14451445

14461446
if !blanket_impls.is_empty() {
1447+
let impls = render_impls(cx, blanket_impls, containing_item, false);
14471448
write!(
14481449
w,
1449-
"{}<div id=\"blanket-implementations-list\">",
1450+
"{}<div id=\"blanket-implementations-list\">{impls}</div>",
14501451
write_impl_section_heading("Blanket Implementations", "blanket-implementations")
14511452
)?;
1452-
render_impls(cx, &mut w, blanket_impls, containing_item, false)?;
1453-
w.write_str("</div>")?;
14541453
}
1454+
14551455
Ok(())
14561456
}
14571457

@@ -1588,14 +1588,7 @@ fn render_assoc_items_inner(
15881588
let (blanket_impls, concrete_impls): (Vec<&Impl>, _) =
15891589
trait_impls.into_iter().partition(|t| t.inner_impl().kind.is_blanket());
15901590

1591-
render_all_impls(
1592-
w,
1593-
cx,
1594-
containing_item,
1595-
&concrete_impls,
1596-
&auto_trait_impls,
1597-
&blanket_impls,
1598-
)?;
1591+
render_all_impls(w, cx, containing_item, concrete_impls, auto_trait_impls, blanket_impls)?;
15991592
}
16001593
Ok(())
16011594
}

src/librustdoc/html/render/print_item.rs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ use crate::formats::item_type::ItemType;
3232
use crate::html::escape::{Escape, EscapeBodyTextWithWbr};
3333
use crate::html::format::{
3434
Ending, PrintWithSpace, full_print_fn_decl, print_abi_with_space, print_constness_with_space,
35-
print_generic_bound, print_generics, print_impl, print_import, print_type, print_where_clause,
36-
visibility_print_with_space,
35+
print_generic_bound, print_generics, print_impl, print_import, print_path, print_type,
36+
print_where_clause, visibility_print_with_space,
3737
};
3838
use crate::html::markdown::{HeadingOffset, MarkdownSummaryLine};
3939
use crate::html::render::sidebar::filters;
@@ -1016,9 +1016,9 @@ fn item_trait(cx: &Context<'_>, it: &clean::Item, t: &clean::Trait) -> impl fmt:
10161016
let (mut synthetic, mut concrete): (Vec<&&Impl>, Vec<&&Impl>) =
10171017
local.iter().partition(|i| i.inner_impl().kind.is_auto());
10181018

1019-
synthetic.sort_by_cached_key(|i| ImplString::new(i, cx));
1020-
concrete.sort_by_cached_key(|i| ImplString::new(i, cx));
1021-
foreign.sort_by_cached_key(|i| ImplString::new(i, cx));
1019+
synthetic.sort_by_cached_key(|i| ImplString::new_impl(i, cx));
1020+
concrete.sort_by_cached_key(|i| ImplString::new_impl(i, cx));
1021+
foreign.sort_by_cached_key(|i| ImplString::new_impl(i, cx));
10221022

10231023
if !foreign.is_empty() {
10241024
write!(
@@ -1969,7 +1969,7 @@ fn item_primitive(cx: &Context<'_>, it: &clean::Item) -> impl fmt::Display {
19691969
let (concrete, synthetic, blanket_impl) =
19701970
get_filtered_impls_for_reference(&cx.shared, it);
19711971

1972-
render_all_impls(w, cx, it, &concrete, &synthetic, &blanket_impl)
1972+
render_all_impls(w, cx, it, concrete, synthetic, blanket_impl)
19731973
}
19741974
})
19751975
}
@@ -2346,16 +2346,21 @@ where
23462346
}
23472347

23482348
#[derive(PartialEq, Eq)]
2349-
struct ImplString {
2349+
pub(super) struct ImplString {
23502350
// Plain text (not HTML text) because this is only used for sorting purposes, and the plain
23512351
// text is much shorter and thus faster to compare.
23522352
cmp_text: String,
23532353
}
23542354

23552355
impl ImplString {
2356-
fn new(i: &Impl, cx: &Context<'_>) -> ImplString {
2356+
fn new_impl(i: &Impl, cx: &Context<'_>) -> Self {
23572357
let impl_ = i.inner_impl();
2358-
ImplString { cmp_text: format!("{:#}", print_impl(impl_, false, cx)) }
2358+
Self { cmp_text: format!("{:#}", print_impl(impl_, false, cx)) }
2359+
}
2360+
2361+
pub(super) fn new_path(i: &Impl, cx: &Context<'_>) -> Option<Self> {
2362+
let path = i.inner_impl().trait_.as_ref()?;
2363+
Some(Self { cmp_text: format!("{:#}", print_path(path, cx)) })
23592364
}
23602365
}
23612366

tests/rustdoc-html/macro/const-rendering-macros-33302.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// https://github.com/rust-lang/rust/issues/33302
2-
#![crate_name="issue_33302"]
2+
#![crate_name = "issue_33302"]
33

44
// Ensure constant and array length values are not taken from source
55
// code, which wreaks havoc with macros.
@@ -25,11 +25,12 @@ macro_rules! make {
2525
}
2626

2727
//@ has issue_33302/struct.S.html \
28-
// '//*[@class="impl"]' 'impl T<[i32; 16]> for S'
29-
//@ has - '//*[@id="associatedconstant.C"]' 'const C: [i32; 16]'
28+
// '//*[@class="impl"]' 'impl T<(i32, i32)> for S'
29+
//@ has - '//*[@id="associatedconstant.C"]' 'const C: (i32, i32)'
3030
//@ has - '//*[@id="associatedconstant.D"]' 'const D: i32'
31-
impl T<[i32; ($n * $n)]> for S {
32-
const C: [i32; ($n * $n)] = [0; ($n * $n)];
31+
impl T<(i32, i32)> for S {
32+
const C: (i32, i32) = ($n, $n);
33+
const D: i32 = ($n / $n);
3334
}
3435

3536
//@ has issue_33302/struct.S.html \
@@ -41,12 +42,11 @@ macro_rules! make {
4142
}
4243

4344
//@ has issue_33302/struct.S.html \
44-
// '//*[@class="impl"]' 'impl T<(i32, i32)> for S'
45-
//@ has - '//*[@id="associatedconstant.C-2"]' 'const C: (i32, i32)'
45+
// '//*[@class="impl"]' 'impl T<[i32; 16]> for S'
46+
//@ has - '//*[@id="associatedconstant.C-2"]' 'const C: [i32; 16]'
4647
//@ has - '//*[@id="associatedconstant.D-2"]' 'const D: i32'
47-
impl T<(i32, i32)> for S {
48-
const C: (i32, i32) = ($n, $n);
49-
const D: i32 = ($n / $n);
48+
impl T<[i32; ($n * $n)]> for S {
49+
const C: [i32; ($n * $n)] = [0; ($n * $n)];
5050
}
5151
};
5252
}

0 commit comments

Comments
 (0)