@@ -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 } ;
@@ -60,8 +61,6 @@ use rustc_middle::ty::print::PrintTraitRefExt;
6061use rustc_middle:: ty:: { self , TyCtxt } ;
6162use rustc_span:: symbol:: { Symbol , sym} ;
6263use rustc_span:: { BytePos , DUMMY_SP , FileName , RealFileName } ;
63- use serde:: ser:: SerializeMap ;
64- use serde:: { Serialize , Serializer } ;
6564use tracing:: { debug, info} ;
6665
6766pub ( crate ) use self :: context:: * ;
@@ -77,7 +76,6 @@ use crate::html::escape::Escape;
7776use crate :: html:: format:: {
7877 Ending , HrefError , PrintWithSpace , href, print_abi_with_space, print_constness_with_space,
7978 print_default_space, print_generic_bounds, print_where_clause, visibility_print_with_space,
80- write_str,
8179} ;
8280use crate :: html:: markdown:: {
8381 HeadingOffset , IdMap , Markdown , MarkdownItemInfo , MarkdownSummaryLine ,
@@ -1477,12 +1475,10 @@ fn render_assoc_items_inner(
14771475 )
14781476 }
14791477 } ;
1480- let mut impls_buf = String :: new ( ) ;
1481- for i in & non_trait {
1482- write_str (
1483- & mut impls_buf,
1484- format_args ! (
1485- "{}" ,
1478+ let impls_buf = fmt:: from_fn ( |f| {
1479+ non_trait
1480+ . iter ( )
1481+ . map ( |i| {
14861482 render_impl (
14871483 cx,
14881484 i,
@@ -1498,9 +1494,11 @@ fn render_assoc_items_inner(
14981494 toggle_open_by_default : true ,
14991495 } ,
15001496 )
1501- ) ,
1502- ) ;
1503- }
1497+ } )
1498+ . joined ( "" , f)
1499+ } )
1500+ . to_string ( ) ;
1501+
15041502 if !impls_buf. is_empty ( ) {
15051503 write ! (
15061504 w,
@@ -1652,91 +1650,85 @@ fn notable_traits_button(ty: &clean::Type, cx: &Context<'_>) -> Option<impl fmt:
16521650}
16531651
16541652fn notable_traits_decl ( ty : & clean:: Type , cx : & Context < ' _ > ) -> ( String , String ) {
1655- let mut out = String :: new ( ) ;
1656-
16571653 let did = ty. def_id ( cx. cache ( ) ) . expect ( "notable_traits_button already checked this" ) ;
16581654
16591655 let impls = cx. cache ( ) . impls . get ( & did) . expect ( "notable_traits_button already checked this" ) ;
16601656
1661- for i in impls {
1662- let impl_ = i. inner_impl ( ) ;
1663- if impl_. polarity != ty:: ImplPolarity :: Positive {
1664- continue ;
1665- }
1666-
1667- if !ty. is_doc_subtype_of ( & impl_. for_ , cx. cache ( ) ) {
1668- // Two different types might have the same did,
1669- // without actually being the same.
1670- continue ;
1671- }
1672- if let Some ( trait_) = & impl_. trait_ {
1673- let trait_did = trait_. def_id ( ) ;
1674-
1675- if cx. cache ( ) . traits . get ( & trait_did) . is_some_and ( |t| t. is_notable_trait ( cx. tcx ( ) ) ) {
1676- if out. is_empty ( ) {
1677- write_str (
1678- & mut out,
1679- format_args ! (
1680- "<h3>Notable traits for <code>{}</code></h3>\
1681- <pre><code>",
1682- impl_. for_. print( cx)
1683- ) ,
1684- ) ;
1657+ let out = fmt:: from_fn ( |f| {
1658+ let mut notable_impls = impls
1659+ . iter ( )
1660+ . map ( |impl_| impl_. inner_impl ( ) )
1661+ . filter ( |impl_| impl_. polarity == ty:: ImplPolarity :: Positive )
1662+ . filter ( |impl_| {
1663+ // Two different types might have the same did, without actually being the same.
1664+ ty. is_doc_subtype_of ( & impl_. for_ , cx. cache ( ) )
1665+ } )
1666+ . filter_map ( |impl_| {
1667+ if let Some ( trait_) = & impl_. trait_
1668+ && let trait_did = trait_. def_id ( )
1669+ && let Some ( trait_) = cx. cache ( ) . traits . get ( & trait_did)
1670+ && trait_. is_notable_trait ( cx. tcx ( ) )
1671+ {
1672+ Some ( ( impl_, trait_did) )
1673+ } else {
1674+ None
16851675 }
1676+ } )
1677+ . peekable ( ) ;
16861678
1687- write_str (
1688- & mut out,
1689- format_args ! ( "<div class=\" where\" >{}</div>" , impl_. print( false , cx) ) ,
1690- ) ;
1691- for it in & impl_. items {
1692- if let clean:: AssocTypeItem ( ref tydef, ref _bounds) = it. kind {
1693- let empty_set = FxIndexSet :: default ( ) ;
1694- let src_link = AssocItemLink :: GotoSource ( trait_did. into ( ) , & empty_set) ;
1695- write_str (
1696- & mut out,
1697- format_args ! (
1698- "<div class=\" where\" > {};</div>" ,
1699- assoc_type(
1700- it,
1701- & tydef. generics,
1702- & [ ] , // intentionally leaving out bounds
1703- Some ( & tydef. type_) ,
1704- src_link,
1705- 0 ,
1706- cx,
1707- )
1708- ) ,
1709- ) ;
1710- }
1711- }
1679+ let has_notable_impl = if let Some ( ( impl_, _) ) = notable_impls. peek ( ) {
1680+ write ! (
1681+ f,
1682+ "<h3>Notable traits for <code>{}</code></h3>\
1683+ <pre><code>",
1684+ impl_. for_. print( cx)
1685+ ) ?;
1686+ true
1687+ } else {
1688+ false
1689+ } ;
1690+
1691+ for ( impl_, trait_did) in notable_impls {
1692+ write ! ( f, "<div class=\" where\" >{}</div>" , impl_. print( false , cx) ) ?;
1693+ for it in & impl_. items {
1694+ let clean:: AssocTypeItem ( tydef, ..) = & it. kind else {
1695+ continue ;
1696+ } ;
1697+
1698+ let empty_set = FxIndexSet :: default ( ) ;
1699+ let src_link = AssocItemLink :: GotoSource ( trait_did. into ( ) , & empty_set) ;
1700+
1701+ write ! (
1702+ f,
1703+ "<div class=\" where\" > {};</div>" ,
1704+ assoc_type(
1705+ it,
1706+ & tydef. generics,
1707+ & [ ] , // intentionally leaving out bounds
1708+ Some ( & tydef. type_) ,
1709+ src_link,
1710+ 0 ,
1711+ cx,
1712+ )
1713+ ) ?;
17121714 }
17131715 }
1714- }
1715- if out. is_empty ( ) {
1716- out. push_str ( "</code></pre>" ) ;
1717- }
1716+
1717+ if !has_notable_impl {
1718+ f. write_str ( "</code></pre>" ) ?;
1719+ }
1720+
1721+ Ok ( ( ) )
1722+ } )
1723+ . to_string ( ) ;
17181724
17191725 ( format ! ( "{:#}" , ty. print( cx) ) , out)
17201726}
17211727
17221728fn notable_traits_json < ' a > ( tys : impl Iterator < Item = & ' a clean:: Type > , cx : & Context < ' _ > ) -> String {
1723- let mut mp: Vec < ( String , String ) > = tys. map ( |ty| notable_traits_decl ( ty, cx) ) . collect ( ) ;
1724- mp. sort_by ( |( name1, _html1) , ( name2, _html2) | name1. cmp ( name2) ) ;
1725- struct NotableTraitsMap ( Vec < ( String , String ) > ) ;
1726- impl Serialize for NotableTraitsMap {
1727- fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
1728- where
1729- S : Serializer ,
1730- {
1731- let mut map = serializer. serialize_map ( Some ( self . 0 . len ( ) ) ) ?;
1732- for item in & self . 0 {
1733- map. serialize_entry ( & item. 0 , & item. 1 ) ?;
1734- }
1735- map. end ( )
1736- }
1737- }
1738- serde_json:: to_string ( & NotableTraitsMap ( mp) )
1739- . expect ( "serialize (string, string) -> json object cannot fail" )
1729+ let mut mp = tys. map ( |ty| notable_traits_decl ( ty, cx) ) . collect :: < IndexMap < _ , _ > > ( ) ;
1730+ mp. sort_unstable_keys ( ) ;
1731+ serde_json:: to_string ( & mp) . expect ( "serialize (string, string) -> json object cannot fail" )
17401732}
17411733
17421734#[ derive( Clone , Copy , Debug ) ]
@@ -1810,49 +1802,34 @@ fn render_impl(
18101802 document_item_info ( cx, it, Some ( parent) )
18111803 . render_into ( & mut info_buffer)
18121804 . unwrap ( ) ;
1813- write_str (
1814- & mut doc_buffer,
1815- format_args ! ( "{}" , document_full( item, cx, HeadingOffset :: H5 ) ) ,
1816- ) ;
1805+ doc_buffer = document_full ( item, cx, HeadingOffset :: H5 ) . to_string ( ) ;
18171806 short_documented = false ;
18181807 } else {
18191808 // In case the item isn't documented,
18201809 // provide short documentation from the trait.
1821- write_str (
1822- & mut doc_buffer,
1823- format_args ! (
1824- "{}" ,
1825- document_short(
1826- it,
1827- cx,
1828- link,
1829- parent,
1830- rendering_params. show_def_docs,
1831- )
1832- ) ,
1833- ) ;
1810+ doc_buffer = document_short (
1811+ it,
1812+ cx,
1813+ link,
1814+ parent,
1815+ rendering_params. show_def_docs ,
1816+ )
1817+ . to_string ( ) ;
18341818 }
18351819 }
18361820 } else {
18371821 document_item_info ( cx, item, Some ( parent) )
18381822 . render_into ( & mut info_buffer)
18391823 . unwrap ( ) ;
18401824 if rendering_params. show_def_docs {
1841- write_str (
1842- & mut doc_buffer,
1843- format_args ! ( "{}" , document_full( item, cx, HeadingOffset :: H5 ) ) ,
1844- ) ;
1825+ doc_buffer = document_full ( item, cx, HeadingOffset :: H5 ) . to_string ( ) ;
18451826 short_documented = false ;
18461827 }
18471828 }
18481829 } else {
1849- write_str (
1850- & mut doc_buffer,
1851- format_args ! (
1852- "{}" ,
1853- document_short( item, cx, link, parent, rendering_params. show_def_docs)
1854- ) ,
1855- ) ;
1830+ doc_buffer =
1831+ document_short ( item, cx, link, parent, rendering_params. show_def_docs )
1832+ . to_string ( ) ;
18561833 }
18571834 }
18581835 let mut w = if short_documented && trait_. is_some ( ) {
0 commit comments