@@ -48,6 +48,7 @@ use std::path::PathBuf;
4848use std:: { fs, str} ;
4949
5050use askama:: Template ;
51+ use indexmap:: IndexMap ;
5152use itertools:: Either ;
5253use rustc_ast:: join_path_syms;
5354use rustc_data_structures:: fx:: { FxHashSet , FxIndexMap , FxIndexSet } ;
@@ -58,8 +59,6 @@ use rustc_middle::ty::print::PrintTraitRefExt;
5859use rustc_middle:: ty:: { self , TyCtxt } ;
5960use rustc_span:: symbol:: { Symbol , sym} ;
6061use rustc_span:: { BytePos , DUMMY_SP , FileName , RealFileName } ;
61- use serde:: ser:: SerializeMap ;
62- use serde:: { Serialize , Serializer } ;
6362use tracing:: { debug, info} ;
6463
6564pub ( crate ) use self :: context:: * ;
@@ -75,7 +74,6 @@ use crate::html::escape::Escape;
7574use crate :: html:: format:: {
7675 Ending , HrefError , PrintWithSpace , href, print_abi_with_space, print_constness_with_space,
7776 print_default_space, print_generic_bounds, print_where_clause, visibility_print_with_space,
78- write_str,
7977} ;
8078use crate :: html:: markdown:: {
8179 HeadingOffset , IdMap , Markdown , MarkdownItemInfo , MarkdownSummaryLine ,
@@ -1507,12 +1505,10 @@ fn render_assoc_items_inner(
15071505 )
15081506 }
15091507 } ;
1510- let mut impls_buf = String :: new ( ) ;
1511- for i in & non_trait {
1512- write_str (
1513- & mut impls_buf,
1514- format_args ! (
1515- "{}" ,
1508+ let impls_buf = fmt:: from_fn ( |f| {
1509+ non_trait
1510+ . iter ( )
1511+ . map ( |i| {
15161512 render_impl (
15171513 cx,
15181514 i,
@@ -1528,9 +1524,11 @@ fn render_assoc_items_inner(
15281524 toggle_open_by_default : true ,
15291525 } ,
15301526 )
1531- ) ,
1532- ) ;
1533- }
1527+ } )
1528+ . joined ( "" , f)
1529+ } )
1530+ . to_string ( ) ;
1531+
15341532 if !impls_buf. is_empty ( ) {
15351533 write ! (
15361534 w,
@@ -1682,91 +1680,85 @@ fn notable_traits_button(ty: &clean::Type, cx: &Context<'_>) -> Option<impl fmt:
16821680}
16831681
16841682fn notable_traits_decl ( ty : & clean:: Type , cx : & Context < ' _ > ) -> ( String , String ) {
1685- let mut out = String :: new ( ) ;
1686-
16871683 let did = ty. def_id ( cx. cache ( ) ) . expect ( "notable_traits_button already checked this" ) ;
16881684
16891685 let impls = cx. cache ( ) . impls . get ( & did) . expect ( "notable_traits_button already checked this" ) ;
16901686
1691- for i in impls {
1692- let impl_ = i. inner_impl ( ) ;
1693- if impl_. polarity != ty:: ImplPolarity :: Positive {
1694- continue ;
1695- }
1696-
1697- if !ty. is_doc_subtype_of ( & impl_. for_ , cx. cache ( ) ) {
1698- // Two different types might have the same did,
1699- // without actually being the same.
1700- continue ;
1701- }
1702- if let Some ( trait_) = & impl_. trait_ {
1703- let trait_did = trait_. def_id ( ) ;
1704-
1705- if cx. cache ( ) . traits . get ( & trait_did) . is_some_and ( |t| t. is_notable_trait ( cx. tcx ( ) ) ) {
1706- if out. is_empty ( ) {
1707- write_str (
1708- & mut out,
1709- format_args ! (
1710- "<h3>Notable traits for <code>{}</code></h3>\
1711- <pre><code>",
1712- impl_. for_. print( cx)
1713- ) ,
1714- ) ;
1687+ let out = fmt:: from_fn ( |f| {
1688+ let mut notable_impls = impls
1689+ . iter ( )
1690+ . map ( |impl_| impl_. inner_impl ( ) )
1691+ . filter ( |impl_| impl_. polarity == ty:: ImplPolarity :: Positive )
1692+ . filter ( |impl_| {
1693+ // Two different types might have the same did, without actually being the same.
1694+ ty. is_doc_subtype_of ( & impl_. for_ , cx. cache ( ) )
1695+ } )
1696+ . filter_map ( |impl_| {
1697+ if let Some ( trait_) = & impl_. trait_
1698+ && let trait_did = trait_. def_id ( )
1699+ && let Some ( trait_) = cx. cache ( ) . traits . get ( & trait_did)
1700+ && trait_. is_notable_trait ( cx. tcx ( ) )
1701+ {
1702+ Some ( ( impl_, trait_did) )
1703+ } else {
1704+ None
17151705 }
1706+ } )
1707+ . peekable ( ) ;
17161708
1717- write_str (
1718- & mut out,
1719- format_args ! ( "<div class=\" where\" >{}</div>" , impl_. print( false , cx) ) ,
1720- ) ;
1721- for it in & impl_. items {
1722- if let clean:: AssocTypeItem ( ref tydef, ref _bounds) = it. kind {
1723- let empty_set = FxIndexSet :: default ( ) ;
1724- let src_link = AssocItemLink :: GotoSource ( trait_did. into ( ) , & empty_set) ;
1725- write_str (
1726- & mut out,
1727- format_args ! (
1728- "<div class=\" where\" > {};</div>" ,
1729- assoc_type(
1730- it,
1731- & tydef. generics,
1732- & [ ] , // intentionally leaving out bounds
1733- Some ( & tydef. type_) ,
1734- src_link,
1735- 0 ,
1736- cx,
1737- )
1738- ) ,
1739- ) ;
1740- }
1741- }
1709+ let has_notable_impl = if let Some ( ( impl_, _) ) = notable_impls. peek ( ) {
1710+ write ! (
1711+ f,
1712+ "<h3>Notable traits for <code>{}</code></h3>\
1713+ <pre><code>",
1714+ impl_. for_. print( cx)
1715+ ) ?;
1716+ true
1717+ } else {
1718+ false
1719+ } ;
1720+
1721+ for ( impl_, trait_did) in notable_impls {
1722+ write ! ( f, "<div class=\" where\" >{}</div>" , impl_. print( false , cx) ) ?;
1723+ for it in & impl_. items {
1724+ let clean:: AssocTypeItem ( tydef, ..) = & it. kind else {
1725+ continue ;
1726+ } ;
1727+
1728+ let empty_set = FxIndexSet :: default ( ) ;
1729+ let src_link = AssocItemLink :: GotoSource ( trait_did. into ( ) , & empty_set) ;
1730+
1731+ write ! (
1732+ f,
1733+ "<div class=\" where\" > {};</div>" ,
1734+ assoc_type(
1735+ it,
1736+ & tydef. generics,
1737+ & [ ] , // intentionally leaving out bounds
1738+ Some ( & tydef. type_) ,
1739+ src_link,
1740+ 0 ,
1741+ cx,
1742+ )
1743+ ) ?;
17421744 }
17431745 }
1744- }
1745- if out. is_empty ( ) {
1746- out. push_str ( "</code></pre>" ) ;
1747- }
1746+
1747+ if !has_notable_impl {
1748+ f. write_str ( "</code></pre>" ) ?;
1749+ }
1750+
1751+ Ok ( ( ) )
1752+ } )
1753+ . to_string ( ) ;
17481754
17491755 ( format ! ( "{:#}" , ty. print( cx) ) , out)
17501756}
17511757
17521758fn notable_traits_json < ' a > ( tys : impl Iterator < Item = & ' a clean:: Type > , cx : & Context < ' _ > ) -> String {
1753- let mut mp: Vec < ( String , String ) > = tys. map ( |ty| notable_traits_decl ( ty, cx) ) . collect ( ) ;
1754- mp. sort_by ( |( name1, _html1) , ( name2, _html2) | name1. cmp ( name2) ) ;
1755- struct NotableTraitsMap ( Vec < ( String , String ) > ) ;
1756- impl Serialize for NotableTraitsMap {
1757- fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
1758- where
1759- S : Serializer ,
1760- {
1761- let mut map = serializer. serialize_map ( Some ( self . 0 . len ( ) ) ) ?;
1762- for item in & self . 0 {
1763- map. serialize_entry ( & item. 0 , & item. 1 ) ?;
1764- }
1765- map. end ( )
1766- }
1767- }
1768- serde_json:: to_string ( & NotableTraitsMap ( mp) )
1769- . expect ( "serialize (string, string) -> json object cannot fail" )
1759+ let mut mp = tys. map ( |ty| notable_traits_decl ( ty, cx) ) . collect :: < IndexMap < _ , _ > > ( ) ;
1760+ mp. sort_unstable_keys ( ) ;
1761+ serde_json:: to_string ( & mp) . expect ( "serialize (string, string) -> json object cannot fail" )
17701762}
17711763
17721764#[ derive( Clone , Copy , Debug ) ]
@@ -1840,49 +1832,34 @@ fn render_impl(
18401832 document_item_info ( cx, it, Some ( parent) )
18411833 . render_into ( & mut info_buffer)
18421834 . unwrap ( ) ;
1843- write_str (
1844- & mut doc_buffer,
1845- format_args ! ( "{}" , document_full( item, cx, HeadingOffset :: H5 ) ) ,
1846- ) ;
1835+ doc_buffer = document_full ( item, cx, HeadingOffset :: H5 ) . to_string ( ) ;
18471836 short_documented = false ;
18481837 } else {
18491838 // In case the item isn't documented,
18501839 // provide short documentation from the trait.
1851- write_str (
1852- & mut doc_buffer,
1853- format_args ! (
1854- "{}" ,
1855- document_short(
1856- it,
1857- cx,
1858- link,
1859- parent,
1860- rendering_params. show_def_docs,
1861- )
1862- ) ,
1863- ) ;
1840+ doc_buffer = document_short (
1841+ it,
1842+ cx,
1843+ link,
1844+ parent,
1845+ rendering_params. show_def_docs ,
1846+ )
1847+ . to_string ( ) ;
18641848 }
18651849 }
18661850 } else {
18671851 document_item_info ( cx, item, Some ( parent) )
18681852 . render_into ( & mut info_buffer)
18691853 . unwrap ( ) ;
18701854 if rendering_params. show_def_docs {
1871- write_str (
1872- & mut doc_buffer,
1873- format_args ! ( "{}" , document_full( item, cx, HeadingOffset :: H5 ) ) ,
1874- ) ;
1855+ doc_buffer = document_full ( item, cx, HeadingOffset :: H5 ) . to_string ( ) ;
18751856 short_documented = false ;
18761857 }
18771858 }
18781859 } else {
1879- write_str (
1880- & mut doc_buffer,
1881- format_args ! (
1882- "{}" ,
1883- document_short( item, cx, link, parent, rendering_params. show_def_docs)
1884- ) ,
1885- ) ;
1860+ doc_buffer =
1861+ document_short ( item, cx, link, parent, rendering_params. show_def_docs )
1862+ . to_string ( ) ;
18861863 }
18871864 }
18881865 let mut w = if short_documented && trait_. is_some ( ) {
0 commit comments