@@ -7,6 +7,7 @@ use rustc_hir as hir;
7
7
use rustc_hir:: def:: CtorKind ;
8
8
use rustc_hir:: def_id:: DefId ;
9
9
use rustc_middle:: middle:: stability;
10
+ use rustc_middle:: ty:: layout:: LayoutError ;
10
11
use rustc_middle:: ty:: TyCtxt ;
11
12
use rustc_span:: hygiene:: MacroKind ;
12
13
use rustc_span:: symbol:: { kw, sym, Symbol } ;
@@ -830,11 +831,12 @@ fn item_typedef(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::T
830
831
831
832
document ( w, cx, it, None ) ;
832
833
834
+ let def_id = it. def_id . expect_real ( ) ;
833
835
// Render any items associated directly to this alias, as otherwise they
834
836
// won't be visible anywhere in the docs. It would be nice to also show
835
837
// associated items from the aliased type (see discussion in #32077), but
836
838
// 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 ) ;
838
840
}
839
841
840
842
fn 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
846
848
} ) ;
847
849
848
850
document ( w, cx, it, None ) ;
851
+
849
852
let mut fields = s
850
853
. fields
851
854
. iter ( )
@@ -880,7 +883,9 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni
880
883
document ( w, cx, field, Some ( it) ) ;
881
884
}
882
885
}
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) ;
884
889
}
885
890
886
891
fn 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
940
945
} ) ;
941
946
942
947
document ( w, cx, it, None ) ;
948
+
943
949
if !e. variants . is_empty ( ) {
944
950
write ! (
945
951
w,
@@ -1014,7 +1020,9 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
1014
1020
render_stability_since ( w, variant, it, cx. tcx ( ) ) ;
1015
1021
}
1016
1022
}
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) ;
1018
1026
}
1019
1027
1020
1028
fn 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
1114
1122
} ) ;
1115
1123
1116
1124
document ( w, cx, it, None ) ;
1125
+
1117
1126
let mut fields = s
1118
1127
. fields
1119
1128
. iter ( )
@@ -1152,7 +1161,9 @@ fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
1152
1161
}
1153
1162
}
1154
1163
}
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) ;
1156
1167
}
1157
1168
1158
1169
fn 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) {
1522
1533
w. write_str ( "</div></details>" ) ;
1523
1534
}
1524
1535
}
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