@@ -48,6 +48,7 @@ use std::path::PathBuf;
48
48
use std:: { fs, str} ;
49
49
50
50
use askama:: Template ;
51
+ use indexmap:: IndexMap ;
51
52
use itertools:: Either ;
52
53
use rustc_ast:: join_path_syms;
53
54
use rustc_data_structures:: fx:: { FxHashSet , FxIndexMap , FxIndexSet } ;
@@ -60,8 +61,6 @@ use rustc_middle::ty::print::PrintTraitRefExt;
60
61
use rustc_middle:: ty:: { self , TyCtxt } ;
61
62
use rustc_span:: symbol:: { Symbol , sym} ;
62
63
use rustc_span:: { BytePos , DUMMY_SP , FileName , RealFileName } ;
63
- use serde:: ser:: SerializeMap ;
64
- use serde:: { Serialize , Serializer } ;
65
64
use tracing:: { debug, info} ;
66
65
67
66
pub ( crate ) use self :: context:: * ;
@@ -77,7 +76,6 @@ use crate::html::escape::Escape;
77
76
use crate :: html:: format:: {
78
77
Ending , HrefError , PrintWithSpace , href, print_abi_with_space, print_constness_with_space,
79
78
print_default_space, print_generic_bounds, print_where_clause, visibility_print_with_space,
80
- write_str,
81
79
} ;
82
80
use crate :: html:: markdown:: {
83
81
HeadingOffset , IdMap , Markdown , MarkdownItemInfo , MarkdownSummaryLine ,
@@ -1477,12 +1475,10 @@ fn render_assoc_items_inner(
1477
1475
)
1478
1476
}
1479
1477
} ;
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| {
1486
1482
render_impl (
1487
1483
cx,
1488
1484
i,
@@ -1498,9 +1494,11 @@ fn render_assoc_items_inner(
1498
1494
toggle_open_by_default : true ,
1499
1495
} ,
1500
1496
)
1501
- ) ,
1502
- ) ;
1503
- }
1497
+ } )
1498
+ . joined ( "" , f)
1499
+ } )
1500
+ . to_string ( ) ;
1501
+
1504
1502
if !impls_buf. is_empty ( ) {
1505
1503
write ! (
1506
1504
w,
@@ -1652,91 +1650,85 @@ fn notable_traits_button(ty: &clean::Type, cx: &Context<'_>) -> Option<impl fmt:
1652
1650
}
1653
1651
1654
1652
fn notable_traits_decl ( ty : & clean:: Type , cx : & Context < ' _ > ) -> ( String , String ) {
1655
- let mut out = String :: new ( ) ;
1656
-
1657
1653
let did = ty. def_id ( cx. cache ( ) ) . expect ( "notable_traits_button already checked this" ) ;
1658
1654
1659
1655
let impls = cx. cache ( ) . impls . get ( & did) . expect ( "notable_traits_button already checked this" ) ;
1660
1656
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
1685
1675
}
1676
+ } )
1677
+ . peekable ( ) ;
1686
1678
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
+ ) ?;
1712
1714
}
1713
1715
}
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 ( ) ;
1718
1724
1719
1725
( format ! ( "{:#}" , ty. print( cx) ) , out)
1720
1726
}
1721
1727
1722
1728
fn 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" )
1740
1732
}
1741
1733
1742
1734
#[ derive( Clone , Copy , Debug ) ]
@@ -1810,49 +1802,34 @@ fn render_impl(
1810
1802
document_item_info ( cx, it, Some ( parent) )
1811
1803
. render_into ( & mut info_buffer)
1812
1804
. 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 ( ) ;
1817
1806
short_documented = false ;
1818
1807
} else {
1819
1808
// In case the item isn't documented,
1820
1809
// 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 ( ) ;
1834
1818
}
1835
1819
}
1836
1820
} else {
1837
1821
document_item_info ( cx, item, Some ( parent) )
1838
1822
. render_into ( & mut info_buffer)
1839
1823
. unwrap ( ) ;
1840
1824
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 ( ) ;
1845
1826
short_documented = false ;
1846
1827
}
1847
1828
}
1848
1829
} 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 ( ) ;
1856
1833
}
1857
1834
}
1858
1835
let mut w = if short_documented && trait_. is_some ( ) {
0 commit comments