@@ -7,6 +7,7 @@ use rustc_hir as hir;
77use rustc_hir:: def:: CtorKind ;
88use rustc_hir:: def_id:: DefId ;
99use rustc_middle:: middle:: stability;
10+ use rustc_middle:: ty:: layout:: LayoutError ;
1011use rustc_middle:: ty:: TyCtxt ;
1112use rustc_span:: hygiene:: MacroKind ;
1213use rustc_span:: symbol:: { kw, sym, Symbol } ;
@@ -830,11 +831,12 @@ fn item_typedef(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::T
830831
831832 document ( w, cx, it, None ) ;
832833
834+ let def_id = it. def_id . expect_real ( ) ;
833835 // Render any items associated directly to this alias, as otherwise they
834836 // won't be visible anywhere in the docs. It would be nice to also show
835837 // associated items from the aliased type (see discussion in #32077), but
836838 // we need #14072 to make sense of the generics.
837- render_assoc_items ( w, cx, it, it . def_id . expect_real ( ) , AssocItemRender :: All )
839+ render_assoc_items ( w, cx, it, def_id, AssocItemRender :: All ) ;
838840}
839841
840842fn item_union ( w : & mut Buffer , cx : & Context < ' _ > , it : & clean:: Item , s : & clean:: Union ) {
@@ -846,6 +848,7 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni
846848 } ) ;
847849
848850 document ( w, cx, it, None ) ;
851+
849852 let mut fields = s
850853 . fields
851854 . iter ( )
@@ -880,7 +883,9 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni
880883 document ( w, cx, field, Some ( it) ) ;
881884 }
882885 }
883- render_assoc_items ( w, cx, it, it. def_id . expect_real ( ) , AssocItemRender :: All )
886+ let def_id = it. def_id . expect_real ( ) ;
887+ render_assoc_items ( w, cx, it, def_id, AssocItemRender :: All ) ;
888+ document_type_layout ( w, cx, def_id) ;
884889}
885890
886891fn item_enum ( w : & mut Buffer , cx : & Context < ' _ > , it : & clean:: Item , e : & clean:: Enum ) {
@@ -940,6 +945,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
940945 } ) ;
941946
942947 document ( w, cx, it, None ) ;
948+
943949 if !e. variants . is_empty ( ) {
944950 write ! (
945951 w,
@@ -1014,7 +1020,9 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
10141020 render_stability_since ( w, variant, it, cx. tcx ( ) ) ;
10151021 }
10161022 }
1017- render_assoc_items ( w, cx, it, it. def_id . expect_real ( ) , AssocItemRender :: All )
1023+ let def_id = it. def_id . expect_real ( ) ;
1024+ render_assoc_items ( w, cx, it, def_id, AssocItemRender :: All ) ;
1025+ document_type_layout ( w, cx, def_id) ;
10181026}
10191027
10201028fn item_macro ( w : & mut Buffer , cx : & Context < ' _ > , it : & clean:: Item , t : & clean:: Macro ) {
@@ -1114,6 +1122,7 @@ fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
11141122 } ) ;
11151123
11161124 document ( w, cx, it, None ) ;
1125+
11171126 let mut fields = s
11181127 . fields
11191128 . iter ( )
@@ -1152,7 +1161,9 @@ fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
11521161 }
11531162 }
11541163 }
1155- render_assoc_items ( w, cx, it, it. def_id . expect_real ( ) , AssocItemRender :: All )
1164+ let def_id = it. def_id . expect_real ( ) ;
1165+ render_assoc_items ( w, cx, it, def_id, AssocItemRender :: All ) ;
1166+ document_type_layout ( w, cx, def_id) ;
11561167}
11571168
11581169fn item_static ( w : & mut Buffer , cx : & Context < ' _ > , it : & clean:: Item , s : & clean:: Static ) {
@@ -1522,3 +1533,62 @@ fn document_non_exhaustive(w: &mut Buffer, item: &clean::Item) {
15221533 w. write_str ( "</div></details>" ) ;
15231534 }
15241535}
1536+
1537+ fn document_type_layout ( w : & mut Buffer , cx : & Context < ' _ > , ty_def_id : DefId ) {
1538+ if !cx. shared . show_type_layout {
1539+ return ;
1540+ }
1541+
1542+ writeln ! ( w, "<h2 class=\" small-section-header\" >Layout</h2>" ) ;
1543+ writeln ! ( w, "<div class=\" docblock\" >" ) ;
1544+
1545+ let tcx = cx. tcx ( ) ;
1546+ let param_env = tcx. param_env ( ty_def_id) ;
1547+ let ty = tcx. type_of ( ty_def_id) ;
1548+ match tcx. layout_of ( param_env. and ( ty) ) {
1549+ Ok ( ty_layout) => {
1550+ writeln ! (
1551+ w,
1552+ "<div class=\" warning\" ><p><strong>Note:</strong> Most layout information is \
1553+ completely unstable and may be different between compiler versions and platforms. \
1554+ The only exception is types with certain <code>repr(...)</code> attributes. \
1555+ Please see the Rust Reference’s \
1556+ <a href=\" https://doc.rust-lang.org/reference/type-layout.html\" >“Type Layout”</a> \
1557+ chapter for details on type layout guarantees.</p></div>"
1558+ ) ;
1559+ if ty_layout. layout . abi . is_unsized ( ) {
1560+ writeln ! ( w, "<p><strong>Size:</strong> (unsized)</p>" ) ;
1561+ } else {
1562+ let bytes = ty_layout. layout . size . bytes ( ) ;
1563+ writeln ! (
1564+ w,
1565+ "<p><strong>Size:</strong> {size} byte{pl}</p>" ,
1566+ size = bytes,
1567+ pl = if bytes == 1 { "" } else { "s" } ,
1568+ ) ;
1569+ }
1570+ }
1571+ // This kind of layout error can occur with valid code, e.g. if you try to
1572+ // get the layout of a generic type such as `Vec<T>`.
1573+ Err ( LayoutError :: Unknown ( _) ) => {
1574+ writeln ! (
1575+ w,
1576+ "<p><strong>Note:</strong> Unable to compute type layout, \
1577+ possibly due to this type having generic parameters. \
1578+ Layout can only be computed for concrete, fully-instantiated types.</p>"
1579+ ) ;
1580+ }
1581+ // This kind of error probably can't happen with valid code, but we don't
1582+ // want to panic and prevent the docs from building, so we just let the
1583+ // user know that we couldn't compute the layout.
1584+ Err ( LayoutError :: SizeOverflow ( _) ) => {
1585+ writeln ! (
1586+ w,
1587+ "<p><strong>Note:</strong> Encountered an error during type layout; \
1588+ the type was too big.</p>"
1589+ ) ;
1590+ }
1591+ }
1592+
1593+ writeln ! ( w, "</div>" ) ;
1594+ }
0 commit comments