@@ -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 } ;
@@ -58,8 +59,6 @@ use rustc_middle::ty::print::PrintTraitRefExt;
58
59
use rustc_middle:: ty:: { self , TyCtxt } ;
59
60
use rustc_span:: symbol:: { Symbol , sym} ;
60
61
use rustc_span:: { BytePos , DUMMY_SP , FileName , RealFileName } ;
61
- use serde:: ser:: SerializeMap ;
62
- use serde:: { Serialize , Serializer } ;
63
62
use tracing:: { debug, info} ;
64
63
65
64
pub ( crate ) use self :: context:: * ;
@@ -75,7 +74,6 @@ use crate::html::escape::Escape;
75
74
use crate :: html:: format:: {
76
75
Ending , HrefError , PrintWithSpace , href, print_abi_with_space, print_constness_with_space,
77
76
print_default_space, print_generic_bounds, print_where_clause, visibility_print_with_space,
78
- write_str,
79
77
} ;
80
78
use crate :: html:: markdown:: {
81
79
HeadingOffset , IdMap , Markdown , MarkdownItemInfo , MarkdownSummaryLine ,
@@ -1507,12 +1505,10 @@ fn render_assoc_items_inner(
1507
1505
)
1508
1506
}
1509
1507
} ;
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| {
1516
1512
render_impl (
1517
1513
cx,
1518
1514
i,
@@ -1528,9 +1524,11 @@ fn render_assoc_items_inner(
1528
1524
toggle_open_by_default : true ,
1529
1525
} ,
1530
1526
)
1531
- ) ,
1532
- ) ;
1533
- }
1527
+ } )
1528
+ . joined ( "" , f)
1529
+ } )
1530
+ . to_string ( ) ;
1531
+
1534
1532
if !impls_buf. is_empty ( ) {
1535
1533
write ! (
1536
1534
w,
@@ -1682,91 +1680,85 @@ fn notable_traits_button(ty: &clean::Type, cx: &Context<'_>) -> Option<impl fmt:
1682
1680
}
1683
1681
1684
1682
fn notable_traits_decl ( ty : & clean:: Type , cx : & Context < ' _ > ) -> ( String , String ) {
1685
- let mut out = String :: new ( ) ;
1686
-
1687
1683
let did = ty. def_id ( cx. cache ( ) ) . expect ( "notable_traits_button already checked this" ) ;
1688
1684
1689
1685
let impls = cx. cache ( ) . impls . get ( & did) . expect ( "notable_traits_button already checked this" ) ;
1690
1686
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
1715
1705
}
1706
+ } )
1707
+ . peekable ( ) ;
1716
1708
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
+ ) ?;
1742
1744
}
1743
1745
}
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 ( ) ;
1748
1754
1749
1755
( format ! ( "{:#}" , ty. print( cx) ) , out)
1750
1756
}
1751
1757
1752
1758
fn 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" )
1770
1762
}
1771
1763
1772
1764
#[ derive( Clone , Copy , Debug ) ]
@@ -1840,49 +1832,34 @@ fn render_impl(
1840
1832
document_item_info ( cx, it, Some ( parent) )
1841
1833
. render_into ( & mut info_buffer)
1842
1834
. 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 ( ) ;
1847
1836
short_documented = false ;
1848
1837
} else {
1849
1838
// In case the item isn't documented,
1850
1839
// 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 ( ) ;
1864
1848
}
1865
1849
}
1866
1850
} else {
1867
1851
document_item_info ( cx, item, Some ( parent) )
1868
1852
. render_into ( & mut info_buffer)
1869
1853
. unwrap ( ) ;
1870
1854
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 ( ) ;
1875
1856
short_documented = false ;
1876
1857
}
1877
1858
}
1878
1859
} 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 ( ) ;
1886
1863
}
1887
1864
}
1888
1865
let mut w = if short_documented && trait_. is_some ( ) {
0 commit comments