@@ -1367,7 +1367,11 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
13671367 write ! ( w, "{name}({})" , print_tuple_struct_fields( cx, s) , ) ;
13681368 }
13691369 clean:: VariantKind :: Struct ( ref s) => {
1370- render_struct ( w, v, None , None , & s. fields , " " , false , cx) ;
1370+ write ! (
1371+ w,
1372+ "{}" ,
1373+ render_struct( v, None , None , & s. fields, " " , false , cx)
1374+ ) ;
13711375 }
13721376 } ,
13731377 _ => unreachable ! ( ) ,
@@ -1585,53 +1589,123 @@ fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &cle
15851589}
15861590
15871591fn item_struct ( w : & mut Buffer , cx : & mut Context < ' _ > , it : & clean:: Item , s : & clean:: Struct ) {
1588- wrap_item ( w, |w| {
1589- write ! ( w, "{}" , render_attributes_in_code( it, cx. tcx( ) ) ) ;
1590- render_struct ( w, it, Some ( & s. generics ) , s. ctor_kind , & s. fields , "" , true , cx) ;
1591- } ) ;
1592+ #[ derive( Template ) ]
1593+ #[ template( path = "item_struct.html" ) ]
1594+ struct ItemStruct < ' a , ' cx > {
1595+ cx : std:: cell:: RefCell < & ' a mut Context < ' cx > > ,
1596+ it : & ' a clean:: Item ,
1597+ s : & ' a clean:: Struct ,
1598+ }
15921599
1593- write ! ( w, "{}" , document( cx, it, None , HeadingOffset :: H2 ) ) ;
1600+ impl < ' a , ' cx : ' a > ItemStruct < ' a , ' cx > {
1601+ fn render_attributes_in_code < ' b > (
1602+ & ' b self ,
1603+ ) -> impl fmt:: Display + Captures < ' a > + ' b + Captures < ' cx > {
1604+ display_fn ( move |f| {
1605+ let tcx = self . cx . borrow ( ) . tcx ( ) ;
1606+ write ! ( f, "{}" , render_attributes_in_code( self . it, tcx) )
1607+ } )
1608+ }
15941609
1595- let mut fields = s
1596- . fields
1597- . iter ( )
1598- . filter_map ( |f| match * f. kind {
1599- clean:: StructFieldItem ( ref ty) => Some ( ( f, ty) ) ,
1600- _ => None ,
1601- } )
1602- . peekable ( ) ;
1603- if let None | Some ( CtorKind :: Fn ) = s. ctor_kind {
1604- if fields. peek ( ) . is_some ( ) {
1605- write ! (
1606- w,
1607- "<h2 id=\" fields\" class=\" fields small-section-header\" >\
1608- {}{}<a href=\" #fields\" class=\" anchor\" >§</a>\
1609- </h2>\
1610- {}",
1611- if s. ctor_kind. is_none( ) { "Fields" } else { "Tuple Fields" } ,
1612- document_non_exhaustive_header( it) ,
1613- document_non_exhaustive( it)
1614- ) ;
1615- for ( index, ( field, ty) ) in fields. enumerate ( ) {
1616- let field_name =
1617- field. name . map_or_else ( || index. to_string ( ) , |sym| sym. as_str ( ) . to_string ( ) ) ;
1618- let id = cx. derive_id ( format ! ( "{}.{}" , ItemType :: StructField , field_name) ) ;
1619- write ! (
1620- w,
1621- "<span id=\" {id}\" class=\" {item_type} small-section-header\" >\
1622- <a href=\" #{id}\" class=\" anchor field\" >§</a>\
1623- <code>{field_name}: {ty}</code>\
1624- </span>",
1625- item_type = ItemType :: StructField ,
1626- ty = ty. print( cx)
1610+ fn render_struct < ' b > ( & ' b self ) -> impl fmt:: Display + Captures < ' a > + ' b + Captures < ' cx > {
1611+ display_fn ( move |f| {
1612+ let cx = self . cx . borrow ( ) ;
1613+ let v = render_struct (
1614+ self . it ,
1615+ Some ( & self . s . generics ) ,
1616+ self . s . ctor_kind ,
1617+ & self . s . fields ,
1618+ "" ,
1619+ true ,
1620+ * cx,
16271621 ) ;
1628- write ! ( w, "{}" , document( cx, field, Some ( it) , HeadingOffset :: H3 ) ) ;
1629- }
1622+ write ! ( f, "{v}" )
1623+ } )
1624+ }
1625+
1626+ fn document < ' b > ( & ' b self ) -> impl fmt:: Display + Captures < ' a > + ' b + Captures < ' cx > {
1627+ display_fn ( move |f| {
1628+ let mut cx = self . cx . borrow_mut ( ) ;
1629+ let v = document ( * cx, self . it , None , HeadingOffset :: H2 ) ;
1630+ write ! ( f, "{v}" )
1631+ } )
1632+ }
1633+
1634+ fn render_fields < ' b > ( & ' b self ) -> impl fmt:: Display + Captures < ' a > + ' b + Captures < ' cx > {
1635+ display_fn ( move |f| {
1636+ let mut fields = self
1637+ . s
1638+ . fields
1639+ . iter ( )
1640+ . filter_map ( |f| match * f. kind {
1641+ clean:: StructFieldItem ( ref ty) => Some ( ( f, ty) ) ,
1642+ _ => None ,
1643+ } )
1644+ . peekable ( ) ;
1645+ if let None | Some ( CtorKind :: Fn ) = self . s . ctor_kind {
1646+ if fields. peek ( ) . is_some ( ) {
1647+ write ! (
1648+ f,
1649+ "<h2 id=\" fields\" class=\" fields small-section-header\" >\
1650+ {}{}<a href=\" #fields\" class=\" anchor\" >§</a>\
1651+ </h2>\
1652+ {}",
1653+ if self . s. ctor_kind. is_none( ) { "Fields" } else { "Tuple Fields" } ,
1654+ document_non_exhaustive_header( self . it) ,
1655+ document_non_exhaustive( self . it)
1656+ ) ?;
1657+ let mut cx = self . cx . borrow_mut ( ) ;
1658+ for ( index, ( field, ty) ) in fields. enumerate ( ) {
1659+ let field_name = field
1660+ . name
1661+ . map_or_else ( || index. to_string ( ) , |sym| sym. as_str ( ) . to_string ( ) ) ;
1662+ let id =
1663+ cx. derive_id ( format ! ( "{}.{}" , ItemType :: StructField , field_name) ) ;
1664+ write ! (
1665+ f,
1666+ "<span id=\" {id}\" class=\" {item_type} small-section-header\" >\
1667+ <a href=\" #{id}\" class=\" anchor field\" >§</a>\
1668+ <code>{field_name}: {ty}</code>\
1669+ </span>",
1670+ ty = ty. print( * cx) ,
1671+ item_type = ItemType :: StructField ,
1672+ ) ?;
1673+ write ! (
1674+ f,
1675+ "{doc}" ,
1676+ doc = document( * cx, field, Some ( self . it) , HeadingOffset :: H3 ) ,
1677+ ) ?;
1678+ }
1679+ }
1680+ }
1681+ Ok ( ( ) )
1682+ } )
1683+ }
1684+
1685+ fn render_assoc_items < ' b > (
1686+ & ' b self ,
1687+ ) -> impl fmt:: Display + Captures < ' a > + ' b + Captures < ' cx > {
1688+ display_fn ( move |f| {
1689+ let mut cx = self . cx . borrow_mut ( ) ;
1690+ let def_id = self . it . item_id . expect_def_id ( ) ;
1691+ let v = render_assoc_items ( * cx, self . it , def_id, AssocItemRender :: All ) ;
1692+ write ! ( f, "{v}" )
1693+ } )
1694+ }
1695+
1696+ fn document_type_layout < ' b > (
1697+ & ' b self ,
1698+ ) -> impl fmt:: Display + Captures < ' a > + ' b + Captures < ' cx > {
1699+ display_fn ( move |f| {
1700+ let cx = self . cx . borrow ( ) ;
1701+ let def_id = self . it . item_id . expect_def_id ( ) ;
1702+ let v = document_type_layout ( * cx, def_id) ;
1703+ write ! ( f, "{v}" )
1704+ } )
16301705 }
16311706 }
1632- let def_id = it. item_id . expect_def_id ( ) ;
1633- write ! ( w, "{}" , render_assoc_items( cx, it, def_id, AssocItemRender :: All ) ) ;
1634- write ! ( w, "{}" , document_type_layout( cx, def_id) ) ;
1707+
1708+ ItemStruct { cx : std:: cell:: RefCell :: new ( cx) , it, s } . render_into ( w) . unwrap ( ) ;
16351709}
16361710
16371711fn item_static ( w : & mut impl fmt:: Write , cx : & mut Context < ' _ > , it : & clean:: Item , s : & clean:: Static ) {
@@ -1869,107 +1943,122 @@ fn render_union<'a, 'cx: 'a>(
18691943 } )
18701944}
18711945
1872- fn render_struct (
1873- mut w : & mut Buffer ,
1874- it : & clean:: Item ,
1875- g : Option < & clean:: Generics > ,
1946+ fn render_struct < ' a , ' cx : ' a > (
1947+ it : & ' a clean:: Item ,
1948+ g : Option < & ' a clean:: Generics > ,
18761949 ty : Option < CtorKind > ,
1877- fields : & [ clean:: Item ] ,
1878- tab : & str ,
1950+ fields : & ' a [ clean:: Item ] ,
1951+ tab : & ' a str ,
18791952 structhead : bool ,
1880- cx : & Context < ' _ > ,
1881- ) {
1882- let tcx = cx. tcx ( ) ;
1883- write ! (
1884- w,
1885- "{}{}{}" ,
1886- visibility_print_with_space( it. visibility( tcx) , it. item_id, cx) ,
1887- if structhead { "struct " } else { "" } ,
1888- it. name. unwrap( )
1889- ) ;
1890- if let Some ( g) = g {
1891- write ! ( w, "{}" , g. print( cx) )
1892- }
1893- match ty {
1894- None => {
1895- let where_displayed =
1896- g. map ( |g| print_where_clause_and_check ( w, g, cx) ) . unwrap_or ( false ) ;
1953+ cx : & ' a Context < ' cx > ,
1954+ ) -> impl fmt:: Display + ' a + Captures < ' cx > {
1955+ display_fn ( move |mut f| {
1956+ let tcx = cx. tcx ( ) ;
1957+ write ! (
1958+ f,
1959+ "{}{}{}" ,
1960+ visibility_print_with_space( it. visibility( tcx) , it. item_id, cx) ,
1961+ if structhead { "struct " } else { "" } ,
1962+ it. name. unwrap( )
1963+ ) ?;
18971964
1898- // If there wasn't a `where` clause, we add a whitespace.
1899- if !where_displayed {
1900- w. write_str ( " {" ) ;
1901- } else {
1902- w. write_str ( "{" ) ;
1903- }
1904- let count_fields =
1905- fields. iter ( ) . filter ( |f| matches ! ( * f. kind, clean:: StructFieldItem ( ..) ) ) . count ( ) ;
1906- let has_visible_fields = count_fields > 0 ;
1907- let toggle = should_hide_fields ( count_fields) ;
1908- if toggle {
1909- toggle_open ( & mut w, format_args ! ( "{} fields" , count_fields) ) ;
1910- }
1911- for field in fields {
1912- if let clean:: StructFieldItem ( ref ty) = * field. kind {
1913- write ! (
1914- w,
1915- "\n {} {}{}: {}," ,
1916- tab,
1917- visibility_print_with_space( field. visibility( tcx) , field. item_id, cx) ,
1918- field. name. unwrap( ) ,
1919- ty. print( cx) ,
1920- ) ;
1921- }
1922- }
1965+ if let Some ( g) = g {
1966+ write ! ( f, "{}" , g. print( cx) ) ?;
1967+ }
19231968
1924- if has_visible_fields {
1925- if it. has_stripped_entries ( ) . unwrap ( ) {
1926- write ! ( w, "\n {} /* private fields */" , tab) ;
1969+ match ty {
1970+ None => {
1971+ let mut buf = Buffer :: html ( ) ;
1972+ let where_displayed =
1973+ g. map ( |g| print_where_clause_and_check ( & mut buf, g, cx) ) . unwrap_or ( false ) ;
1974+ write ! ( f, "{}" , buf. into_inner( ) ) ?;
1975+
1976+ // If there wasn't a `where` clause, we add a whitespace.
1977+ if !where_displayed {
1978+ f. write_str ( " {" ) ?;
1979+ } else {
1980+ f. write_str ( "{" ) ?;
19271981 }
1928- write ! ( w, "\n {}" , tab) ;
1929- } else if it. has_stripped_entries ( ) . unwrap ( ) {
1930- write ! ( w, " /* private fields */ " ) ;
1931- }
1932- if toggle {
1933- toggle_close ( & mut w) ;
1934- }
1935- w. write_str ( "}" ) ;
1936- }
1937- Some ( CtorKind :: Fn ) => {
1938- w. write_str ( "(" ) ;
1939- for ( i, field) in fields. iter ( ) . enumerate ( ) {
1940- if i > 0 {
1941- w. write_str ( ", " ) ;
1982+
1983+ let count_fields = fields
1984+ . iter ( )
1985+ . filter ( |item| matches ! ( * item. kind, clean:: StructFieldItem ( ..) ) )
1986+ . count ( ) ;
1987+ let has_visible_fields = count_fields > 0 ;
1988+ let toggle = should_hide_fields ( count_fields) ;
1989+ if toggle {
1990+ toggle_open ( & mut f, format_args ! ( "{} fields" , count_fields) ) ;
19421991 }
1943- match * field. kind {
1944- clean:: StrippedItem ( box clean:: StructFieldItem ( ..) ) => write ! ( w, "_" ) ,
1945- clean:: StructFieldItem ( ref ty) => {
1992+ for field in fields {
1993+ if let clean:: StructFieldItem ( ref ty) = * field. kind {
19461994 write ! (
1947- w,
1948- "{}{}" ,
1995+ f,
1996+ "\n {} {}{}: {}," ,
1997+ tab,
19491998 visibility_print_with_space( field. visibility( tcx) , field. item_id, cx) ,
1999+ field. name. unwrap( ) ,
19502000 ty. print( cx) ,
1951- )
2001+ ) ? ;
19522002 }
1953- _ => unreachable ! ( ) ,
19542003 }
2004+
2005+ if has_visible_fields {
2006+ if it. has_stripped_entries ( ) . unwrap ( ) {
2007+ write ! ( f, "\n {} /* private fields */" , tab) ?;
2008+ }
2009+ write ! ( f, "\n {}" , tab) ?;
2010+ } else if it. has_stripped_entries ( ) . unwrap ( ) {
2011+ write ! ( f, " /* private fields */ " ) ?;
2012+ }
2013+ if toggle {
2014+ toggle_close ( & mut f) ;
2015+ }
2016+ f. write_str ( "}" ) ?;
19552017 }
1956- w. write_str ( ")" ) ;
1957- if let Some ( g) = g {
1958- write ! ( w, "{}" , print_where_clause( g, cx, 0 , Ending :: NoNewline ) ) ;
1959- }
1960- // We only want a ";" when we are displaying a tuple struct, not a variant tuple struct.
1961- if structhead {
1962- w. write_str ( ";" ) ;
2018+ Some ( CtorKind :: Fn ) => {
2019+ write ! ( f, "(" ) ?;
2020+ for ( i, field) in fields. iter ( ) . enumerate ( ) {
2021+ if i > 0 {
2022+ write ! ( f, ", " ) ?;
2023+ }
2024+ match * field. kind {
2025+ clean:: StrippedItem ( box clean:: StructFieldItem ( ..) ) => {
2026+ write ! ( f, "_" ) ?;
2027+ }
2028+ clean:: StructFieldItem ( ref ty) => {
2029+ write ! (
2030+ f,
2031+ "{}{}" ,
2032+ visibility_print_with_space(
2033+ field. visibility( tcx) ,
2034+ field. item_id,
2035+ cx
2036+ ) ,
2037+ ty. print( cx) ,
2038+ ) ?;
2039+ }
2040+ _ => unreachable ! ( ) ,
2041+ }
2042+ }
2043+ write ! ( f, ")" ) ?;
2044+ if let Some ( g) = g {
2045+ write ! ( f, "{}" , print_where_clause( g, cx, 0 , Ending :: NoNewline ) ) ?;
2046+ }
2047+ // We only want a ";" when we are displaying a tuple struct, not a variant tuple struct.
2048+ if structhead {
2049+ write ! ( f, ";" ) ?;
2050+ }
19632051 }
1964- }
1965- Some ( CtorKind :: Const ) => {
1966- // Needed for PhantomData.
1967- if let Some ( g) = g {
1968- write ! ( w, "{}" , print_where_clause( g, cx, 0 , Ending :: NoNewline ) ) ;
2052+ Some ( CtorKind :: Const ) => {
2053+ // Needed for PhantomData.
2054+ if let Some ( g) = g {
2055+ write ! ( f, "{}" , print_where_clause( g, cx, 0 , Ending :: NoNewline ) ) ?;
2056+ }
2057+ write ! ( f, ";" ) ?;
19692058 }
1970- w. write_str ( ";" ) ;
19712059 }
1972- }
2060+ Ok ( ( ) )
2061+ } )
19732062}
19742063
19752064fn document_non_exhaustive_header ( item : & clean:: Item ) -> & str {
0 commit comments