From 043c6dba36e55c944e498a378d7323d922851c07 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sun, 31 May 2026 11:14:10 +1000 Subject: [PATCH 1/3] Add a missing alternate case to `print_where_clause`. Currently impls printed in alternate mode use plain text for the first part and HTML for the where clause. This commit fixes the where clause so it's also plain text. --- src/librustdoc/html/format.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index e6c64ef8b4220..312931024e7c4 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -184,9 +184,9 @@ pub(crate) fn print_where_clause( let clause = if f.alternate() { if ending == Ending::Newline { - format!(" where{where_preds},") + format!(" where{where_preds:#},") } else { - format!(" where{where_preds}") + format!(" where{where_preds:#}") } } else { let mut br_with_padding = String::with_capacity(6 * indent + 28); From 60b4da52ed31831ee8ca8e7f58f5a23436dbfea9 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sun, 31 May 2026 10:55:40 +1000 Subject: [PATCH 2/3] Sort impls using plain text, not HTML. These sorts are hot, so it's significantly faster to use concise plain text rather than verbose HTML. --- src/librustdoc/html/format.rs | 3 +-- src/librustdoc/html/render/print_item.rs | 8 +++++--- src/librustdoc/html/render/write_shared.rs | 10 ++++++++-- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 312931024e7c4..cbb5fed8c4d09 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -4,8 +4,7 @@ //! various types in `rustdoc::clean`. //! //! These implementations all emit HTML. As an internal implementation detail, -//! some of them support an alternate format that emits text, but that should -//! not be used external to this module. +//! some of them support an alternate format that emits plain text. use std::cmp::Ordering; use std::fmt::{self, Display, Write}; diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 336513804e1ff..575c4949a8264 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -2324,7 +2324,9 @@ where #[derive(PartialEq, Eq)] struct ImplString { - rendered: String, + // Plain text (not HTML text) because this is only used for sorting purposes, and the plain + // text is much shorter and thus faster to compare. + cmp_text: String, is_negative: bool, } @@ -2333,7 +2335,7 @@ impl ImplString { let impl_ = i.inner_impl(); ImplString { is_negative: impl_.is_negative_trait_impl(), - rendered: format!("{}", print_impl(impl_, false, cx)), + cmp_text: format!("{:#}", print_impl(impl_, false, cx)), } } } @@ -2350,7 +2352,7 @@ impl Ord for ImplString { match (self.is_negative, other.is_negative) { (false, true) => Ordering::Greater, (true, false) => Ordering::Less, - _ => compare_names(&self.rendered, &other.rendered), + _ => compare_names(&self.cmp_text, &other.cmp_text), } } } diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index 26894a64c6c14..f0edbe441ad00 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -730,8 +730,10 @@ impl TraitAliasPart { None } else { let impl_ = imp.inner_impl(); + let print = print_impl(impl_, false, cx); Some(Implementor { - text: print_impl(impl_, false, cx).to_string(), + text: format!("{}", print), + cmp_text: format!("{:#}", print), synthetic: imp.inner_impl().kind.is_auto(), types: collect_paths_for_type(&imp.inner_impl().for_, cache), is_negative: impl_.is_negative_trait_impl(), @@ -759,7 +761,7 @@ impl TraitAliasPart { match (a.is_negative, b.is_negative) { (false, true) => Ordering::Greater, (true, false) => Ordering::Less, - _ => compare_names(&a.text, &b.text), + _ => compare_names(&a.cmp_text, &b.cmp_text), } }); @@ -777,7 +779,11 @@ impl TraitAliasPart { } struct Implementor { + // HTML text used in generated output. text: String, + // Plain text used just for sorting output. This is a performance win, because this plain text + // is much shorter than the HTML output and sorting is hot. + cmp_text: String, synthetic: bool, types: Vec, is_negative: bool, From f7c8bc2b13e6c4af20da615839feb6000f8cba6c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Sun, 31 May 2026 13:09:17 +1000 Subject: [PATCH 3/3] Don't explicitly sort negative impls first. We don't need to because the char ordering works out naturally. --- src/librustdoc/html/render/print_item.rs | 15 ++++----------- src/librustdoc/html/render/write_shared.rs | 12 +++--------- 2 files changed, 7 insertions(+), 20 deletions(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 575c4949a8264..49a8c077188dd 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -2327,16 +2327,12 @@ struct ImplString { // Plain text (not HTML text) because this is only used for sorting purposes, and the plain // text is much shorter and thus faster to compare. cmp_text: String, - is_negative: bool, } impl ImplString { fn new(i: &Impl, cx: &Context<'_>) -> ImplString { let impl_ = i.inner_impl(); - ImplString { - is_negative: impl_.is_negative_trait_impl(), - cmp_text: format!("{:#}", print_impl(impl_, false, cx)), - } + ImplString { cmp_text: format!("{:#}", print_impl(impl_, false, cx)) } } } @@ -2348,12 +2344,9 @@ impl PartialOrd for ImplString { impl Ord for ImplString { fn cmp(&self, other: &Self) -> Ordering { - // We sort negative impls first. - match (self.is_negative, other.is_negative) { - (false, true) => Ordering::Greater, - (true, false) => Ordering::Less, - _ => compare_names(&self.cmp_text, &other.cmp_text), - } + // Negative impls are naturally sorted first, because `impl !A` is less than `impl B` for + // any value of `B`, because `!` is less than any identifier-starting char. + compare_names(&self.cmp_text, &other.cmp_text) } } diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index f0edbe441ad00..c366af8778ed6 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -14,7 +14,6 @@ //! or contains "invocation-specific". use std::cell::RefCell; -use std::cmp::Ordering; use std::ffi::{OsStr, OsString}; use std::fs::File; use std::io::{self, Write as _}; @@ -756,14 +755,9 @@ impl TraitAliasPart { path.push(format!("{remote_item_type}.{}.js", remote_path[remote_path.len() - 1])); let mut implementors = implementors.collect::>(); - implementors.sort_unstable_by(|a, b| { - // We sort negative impls first. - match (a.is_negative, b.is_negative) { - (false, true) => Ordering::Greater, - (true, false) => Ordering::Less, - _ => compare_names(&a.cmp_text, &b.cmp_text), - } - }); + // Negative impls are naturally sorted first, because `impl !A` is less than `impl B` + // for any value of `B`, because `!` is less than any identifier-starting char. + implementors.sort_unstable_by(|a, b| compare_names(&a.cmp_text, &b.cmp_text)); let part = OrderedJson::array_unsorted( implementors