From 001f0dd5a1a544ac9373f0d18e13014ec18dff94 Mon Sep 17 00:00:00 2001 From: Camelid Date: Sun, 21 Mar 2021 19:21:45 -0700 Subject: [PATCH 01/15] rustdoc: Show basic type layout information Right now it just shows the size. --- src/librustdoc/html/render/print_item.rs | 39 ++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 7ccc313cc5905..9b7006150b7f1 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -846,6 +846,7 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni }); document(w, cx, it, None); + let mut fields = s .fields .iter() @@ -880,7 +881,9 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni document(w, cx, field, Some(it)); } } - render_assoc_items(w, cx, it, it.def_id.expect_real(), AssocItemRender::All) + let def_id = it.def_id.expect_real(); + render_assoc_items(w, cx, it, def_id, AssocItemRender::All); + document_ty_layout(w, cx, def_id); } fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum) { @@ -940,6 +943,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum }); document(w, cx, it, None); + if !e.variants.is_empty() { write!( w, @@ -1014,7 +1018,9 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum render_stability_since(w, variant, it, cx.tcx()); } } - render_assoc_items(w, cx, it, it.def_id.expect_real(), AssocItemRender::All) + let def_id = it.def_id.expect_real(); + render_assoc_items(w, cx, it, def_id, AssocItemRender::All); + document_ty_layout(w, cx, def_id); } fn item_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Macro) { @@ -1114,6 +1120,7 @@ fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St }); document(w, cx, it, None); + let mut fields = s .fields .iter() @@ -1152,7 +1159,9 @@ fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St } } } - render_assoc_items(w, cx, it, it.def_id.expect_real(), AssocItemRender::All) + let def_id = it.def_id.expect_real(); + render_assoc_items(w, cx, it, def_id, AssocItemRender::All); + document_ty_layout(w, cx, def_id); } fn item_static(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Static) { @@ -1522,3 +1531,27 @@ fn document_non_exhaustive(w: &mut Buffer, item: &clean::Item) { w.write_str(""); } } + +fn document_ty_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) { + let param_env = cx.tcx().param_env(ty_def_id); + let ty = cx.tcx().type_of(ty_def_id); + match cx.tcx().layout_of(param_env.and(ty)) { + Ok(ty_layout) => { + writeln!(w, r#"

Layout

"#); + writeln!(w, "
"); + if ty_layout.layout.abi.is_unsized() { + writeln!(w, "Sized: (unsized)"); + } else { + writeln!( + w, + "Size: {size} byte{pl}", + size = ty_layout.layout.size.bytes(), + pl = if ty_layout.layout.size.bytes() == 1 { "" } else { "s" }, + ); + } + writeln!(w, "
"); + } + // FIXME: should we crash instead? or report an error? + Err(_layout_err) => {} + } +} From 5859c5d333465fe91be46196e2b47bff9fc48ece Mon Sep 17 00:00:00 2001 From: Camelid Date: Wed, 7 Apr 2021 20:55:37 -0700 Subject: [PATCH 02/15] Remove FIXME Layout errors can occur with valid code, e.g. generic types. --- src/librustdoc/html/render/print_item.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 9b7006150b7f1..1f7b317a45b8d 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1551,7 +1551,9 @@ fn document_ty_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) { } writeln!(w, ""); } - // FIXME: should we crash instead? or report an error? - Err(_layout_err) => {} + // Layout errors can occur with valid code, e.g. if you try to get the layout + // of a generic type such as `Vec`. In case of a layout error, we just + // don't show any layout information. + Err(_) => {} } } From 20b30acfa856309857e8914fb2bb5f831e991d0b Mon Sep 17 00:00:00 2001 From: Camelid Date: Thu, 8 Apr 2021 16:04:21 -0700 Subject: [PATCH 03/15] Include a warning in the layout docs that layout is unstable --- src/librustdoc/html/render/print_item.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 1f7b317a45b8d..41565019c6b19 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1537,10 +1537,19 @@ fn document_ty_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) { let ty = cx.tcx().type_of(ty_def_id); match cx.tcx().layout_of(param_env.and(ty)) { Ok(ty_layout) => { - writeln!(w, r#"

Layout

"#); - writeln!(w, "
"); + writeln!(w, "

Layout

"); + writeln!(w, "
"); + writeln!( + w, + "

Note: Most layout information is \ + completely unstable and may be different between compiler versions. \ + The only exception is types with certain repr(...) attributes. \ + Please see the Rust Reference’s \ + “Type Layout” \ + chapter for details on type layout guarantees.

" + ); if ty_layout.layout.abi.is_unsized() { - writeln!(w, "Sized: (unsized)"); + writeln!(w, "

Size: (unsized)

"); } else { writeln!( w, From 9859e2b01d2498ea0465a36bf4055d45e1f96f5b Mon Sep 17 00:00:00 2001 From: Camelid Date: Mon, 12 Apr 2021 19:06:15 -0700 Subject: [PATCH 04/15] Add test for memory layout information --- src/test/rustdoc/type-layout.rs | 43 +++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 src/test/rustdoc/type-layout.rs diff --git a/src/test/rustdoc/type-layout.rs b/src/test/rustdoc/type-layout.rs new file mode 100644 index 0000000000000..261f407a9063b --- /dev/null +++ b/src/test/rustdoc/type-layout.rs @@ -0,0 +1,43 @@ +// @has type_layout/struct.Foo.html 'Size: ' +// @has - ' bytes' +pub struct Foo { + pub a: usize, + b: Vec, +} + +// @has type_layout/enum.Bar.html 'Size: ' +// @has - ' bytes' +pub enum Bar<'a> { + A(String), + B(&'a str, (std::collections::HashMap, Foo)), +} + +// @has type_layout/union.Baz.html 'Size: ' +// @has - ' bytes' +pub union Baz { + a: &'static str, + b: usize, + c: &'static [u8], +} + +// @has type_layout/struct.X.html 'Size: ' +// @has - ' bytes' +pub struct X(usize); + +// @has type_layout/struct.Y.html 'Size: ' +// @has - ' byte' +// @!has - ' bytes' +pub struct Y(u8); + +// @!has type_layout/struct.Generic.html 'Size: ' +pub struct Generic(T); + +// @has type_layout/struct.Unsized.html 'Size: ' +// @has - '(unsized)' +pub struct Unsized([u8]); + +// @!has type_layout/type.TypeAlias.html 'Size: ' +pub type TypeAlias = X; + +// @!has type_layout/trait.MyTrait.html 'Size: ' +pub trait MyTrait {} From 48da66f28f078c0dc31068a30977e9079c876d90 Mon Sep 17 00:00:00 2001 From: Camelid Date: Mon, 12 Apr 2021 19:23:49 -0700 Subject: [PATCH 05/15] Show memory layout for type aliases At first you might think "why not just click through to the aliased type?", but if a type alias instantiates all of the generic parameters of the aliased type, then it can show layout info even though the aliased type cannot (because we can't compute the layout of a generic type). So I think it's still useful to show layout info for type aliases. --- src/librustdoc/html/render/print_item.rs | 5 ++++- src/test/rustdoc/type-layout.rs | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 41565019c6b19..9ac9ee66f6a86 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -830,11 +830,14 @@ fn item_typedef(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::T document(w, cx, it, None); + let def_id = it.def_id.expect_real(); // Render any items associated directly to this alias, as otherwise they // won't be visible anywhere in the docs. It would be nice to also show // associated items from the aliased type (see discussion in #32077), but // we need #14072 to make sense of the generics. - render_assoc_items(w, cx, it, it.def_id.expect_real(), AssocItemRender::All) + render_assoc_items(w, cx, it, def_id, AssocItemRender::All); + + document_ty_layout(w, cx, def_id); } fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Union) { diff --git a/src/test/rustdoc/type-layout.rs b/src/test/rustdoc/type-layout.rs index 261f407a9063b..e18bdeba91352 100644 --- a/src/test/rustdoc/type-layout.rs +++ b/src/test/rustdoc/type-layout.rs @@ -36,7 +36,8 @@ pub struct Generic(T); // @has - '(unsized)' pub struct Unsized([u8]); -// @!has type_layout/type.TypeAlias.html 'Size: ' +// @has type_layout/type.TypeAlias.html 'Size: ' +// @has - ' bytes' pub type TypeAlias = X; // @!has type_layout/trait.MyTrait.html 'Size: ' From 12ee920a7c3aa237eb7e207e128120f5a639743a Mon Sep 17 00:00:00 2001 From: Camelid Date: Mon, 12 Apr 2021 19:42:26 -0700 Subject: [PATCH 06/15] Only show type layout info if `--show-type-layout` is passed --- src/librustdoc/config.rs | 4 ++++ src/librustdoc/html/render/context.rs | 4 ++++ src/librustdoc/html/render/print_item.rs | 4 ++++ src/librustdoc/lib.rs | 3 +++ src/test/rustdoc/type-layout-flag-required.rs | 4 ++++ src/test/rustdoc/type-layout.rs | 2 ++ 6 files changed, 21 insertions(+) create mode 100644 src/test/rustdoc/type-layout-flag-required.rs diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 045b42d0dcaf7..b75e98ae16c16 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -267,6 +267,8 @@ crate struct RenderOptions { crate document_hidden: bool, /// If `true`, generate a JSON file in the crate folder instead of HTML redirection files. crate generate_redirect_map: bool, + /// Show the memory layout of types in the docs. + crate show_type_layout: bool, crate unstable_features: rustc_feature::UnstableFeatures, crate emit: Vec, } @@ -636,6 +638,7 @@ impl Options { let document_hidden = matches.opt_present("document-hidden-items"); let run_check = matches.opt_present("check"); let generate_redirect_map = matches.opt_present("generate-redirect-map"); + let show_type_layout = matches.opt_present("show-type-layout"); let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format); @@ -695,6 +698,7 @@ impl Options { document_private, document_hidden, generate_redirect_map, + show_type_layout, unstable_features: rustc_feature::UnstableFeatures::from_environment( crate_name.as_deref(), ), diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 4e17dc8d3a7d0..666d9dfc3e9e4 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -91,6 +91,8 @@ crate struct SharedContext<'tcx> { crate include_sources: bool, /// The local file sources we've emitted and their respective url-paths. crate local_sources: FxHashMap, + /// Show the memory layout of types in the docs. + pub(super) show_type_layout: bool, /// Whether the collapsed pass ran collapsed: bool, /// The base-URL of the issue tracker for when an item has been tagged with @@ -373,6 +375,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { generate_search_filter, unstable_features, generate_redirect_map, + show_type_layout, .. } = options; @@ -446,6 +449,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { all: RefCell::new(AllTypes::new()), errors: receiver, redirections: if generate_redirect_map { Some(Default::default()) } else { None }, + show_type_layout, }; // Add the default themes to the `Vec` of stylepaths diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 9ac9ee66f6a86..2de1a2226f5c2 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1536,6 +1536,10 @@ fn document_non_exhaustive(w: &mut Buffer, item: &clean::Item) { } fn document_ty_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) { + if !cx.shared.show_type_layout { + return; + } + let param_env = cx.tcx().param_env(ty_def_id); let ty = cx.tcx().type_of(ty_def_id); match cx.tcx().layout_of(param_env.and(ty)) { diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 169ef015fa88c..5ede3780e87ae 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -594,6 +594,9 @@ fn opts() -> Vec { ) }), unstable("no-run", |o| o.optflag("", "no-run", "Compile doctests without running them")), + unstable("show-type-layout", |o| { + o.optflag("", "show-type-layout", "Include the memory layout of types in the docs") + }), ] } diff --git a/src/test/rustdoc/type-layout-flag-required.rs b/src/test/rustdoc/type-layout-flag-required.rs new file mode 100644 index 0000000000000..a01fbd229508b --- /dev/null +++ b/src/test/rustdoc/type-layout-flag-required.rs @@ -0,0 +1,4 @@ +// Tests that `--show-type-layout` is required in order to show layout info. + +// @!has type_layout_flag_required/struct.Foo.html 'Size: ' +pub struct Foo(usize); diff --git a/src/test/rustdoc/type-layout.rs b/src/test/rustdoc/type-layout.rs index e18bdeba91352..9fd8f92aeb976 100644 --- a/src/test/rustdoc/type-layout.rs +++ b/src/test/rustdoc/type-layout.rs @@ -1,3 +1,5 @@ +// compile-flags: --show-type-layout -Z unstable-options + // @has type_layout/struct.Foo.html 'Size: ' // @has - ' bytes' pub struct Foo { From 9615d6dd48489a4700b31b301fe1a45cfa3e536e Mon Sep 17 00:00:00 2001 From: Camelid Date: Mon, 12 Apr 2021 19:43:55 -0700 Subject: [PATCH 07/15] Enable `--show-type-layout` for the rustc API docs --- src/bootstrap/doc.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index a32b92ef1af83..e42d4fcd8647c 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -549,6 +549,7 @@ impl Step for Rustc { cargo.rustdocflag("--enable-index-page"); cargo.rustdocflag("-Zunstable-options"); cargo.rustdocflag("-Znormalize-docs"); + cargo.rustdocflag("--show-type-layout"); compile::rustc_cargo(builder, &mut cargo, target); // Only include compiler crates, no dependencies of those, such as `libc`. From db3a06d01eb517448954ec0eaccd68f88be988e0 Mon Sep 17 00:00:00 2001 From: Camelid Date: Mon, 12 Apr 2021 20:13:19 -0700 Subject: [PATCH 08/15] Fix a few small things --- src/librustdoc/html/render/print_item.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 2de1a2226f5c2..1fe445b2ea1ba 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -837,7 +837,7 @@ fn item_typedef(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::T // we need #14072 to make sense of the generics. render_assoc_items(w, cx, it, def_id, AssocItemRender::All); - document_ty_layout(w, cx, def_id); + document_type_layout(w, cx, def_id); } fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Union) { @@ -886,7 +886,7 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni } let def_id = it.def_id.expect_real(); render_assoc_items(w, cx, it, def_id, AssocItemRender::All); - document_ty_layout(w, cx, def_id); + document_type_layout(w, cx, def_id); } fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum) { @@ -1023,7 +1023,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum } let def_id = it.def_id.expect_real(); render_assoc_items(w, cx, it, def_id, AssocItemRender::All); - document_ty_layout(w, cx, def_id); + document_type_layout(w, cx, def_id); } fn item_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Macro) { @@ -1164,7 +1164,7 @@ fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St } let def_id = it.def_id.expect_real(); render_assoc_items(w, cx, it, def_id, AssocItemRender::All); - document_ty_layout(w, cx, def_id); + document_type_layout(w, cx, def_id); } fn item_static(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Static) { @@ -1535,7 +1535,7 @@ fn document_non_exhaustive(w: &mut Buffer, item: &clean::Item) { } } -fn document_ty_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) { +fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) { if !cx.shared.show_type_layout { return; } @@ -1560,7 +1560,7 @@ fn document_ty_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) { } else { writeln!( w, - "Size: {size} byte{pl}", + "

Size: {size} byte{pl}

", size = ty_layout.layout.size.bytes(), pl = if ty_layout.layout.size.bytes() == 1 { "" } else { "s" }, ); From 8048c705688fbd0822fe134210556f9af79e8f85 Mon Sep 17 00:00:00 2001 From: Camelid Date: Tue, 13 Apr 2021 18:33:25 -0700 Subject: [PATCH 09/15] Add `tcx` local variable --- src/librustdoc/html/render/print_item.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 1fe445b2ea1ba..a2d1a6a23c63b 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1540,9 +1540,10 @@ fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) { return; } - let param_env = cx.tcx().param_env(ty_def_id); - let ty = cx.tcx().type_of(ty_def_id); - match cx.tcx().layout_of(param_env.and(ty)) { + let tcx = cx.tcx(); + let param_env = tcx.param_env(ty_def_id); + let ty = tcx.type_of(ty_def_id); + match tcx.layout_of(param_env.and(ty)) { Ok(ty_layout) => { writeln!(w, "

Layout

"); writeln!(w, "
"); From bcbc72767288ac2723213d0b02dfe1f98cc27948 Mon Sep 17 00:00:00 2001 From: Camelid Date: Fri, 23 Apr 2021 14:01:00 -0700 Subject: [PATCH 10/15] Apply suggestions from code review Co-authored-by: Ivan Tham --- src/librustdoc/html/render/print_item.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index a2d1a6a23c63b..af7745d6126c9 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1550,7 +1550,7 @@ fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) { writeln!( w, "

Note: Most layout information is \ - completely unstable and may be different between compiler versions. \ + completely unstable and may be different between compiler versions and platforms. \ The only exception is types with certain repr(...) attributes. \ Please see the Rust Reference’s \ “Type Layout” \ @@ -1559,11 +1559,12 @@ fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) { if ty_layout.layout.abi.is_unsized() { writeln!(w, "

Size: (unsized)

"); } else { + let bytes = ty_layout.layout.size.bytes(); writeln!( w, "

Size: {size} byte{pl}

", - size = ty_layout.layout.size.bytes(), - pl = if ty_layout.layout.size.bytes() == 1 { "" } else { "s" }, + size = bytes, + pl = if bytes == 1 { "" } else { "s" }, ); } writeln!(w, "
"); From 61a84794726c94dd297a7b0fd0321a1d4a6d08dd Mon Sep 17 00:00:00 2001 From: Camelid Date: Fri, 23 Apr 2021 14:10:51 -0700 Subject: [PATCH 11/15] Make test more specific --- src/test/rustdoc/type-layout.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/rustdoc/type-layout.rs b/src/test/rustdoc/type-layout.rs index 9fd8f92aeb976..72e2830040524 100644 --- a/src/test/rustdoc/type-layout.rs +++ b/src/test/rustdoc/type-layout.rs @@ -27,7 +27,7 @@ pub union Baz { pub struct X(usize); // @has type_layout/struct.Y.html 'Size: ' -// @has - ' byte' +// @has - '1 byte' // @!has - ' bytes' pub struct Y(u8); From 879a914eea7d8d10bf865822e76a165938e41544 Mon Sep 17 00:00:00 2001 From: Camelid Date: Tue, 27 Apr 2021 10:38:12 -0700 Subject: [PATCH 12/15] Add test case for zero-sized types --- src/test/rustdoc/type-layout.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/test/rustdoc/type-layout.rs b/src/test/rustdoc/type-layout.rs index 72e2830040524..cb6e354f7df54 100644 --- a/src/test/rustdoc/type-layout.rs +++ b/src/test/rustdoc/type-layout.rs @@ -31,6 +31,10 @@ pub struct X(usize); // @!has - ' bytes' pub struct Y(u8); +// @has type_layout/struct.Z.html 'Size: ' +// @has - '0 bytes' +pub struct Z; + // @!has type_layout/struct.Generic.html 'Size: ' pub struct Generic(T); From 8b9298bbaaa1e1803f1ca4040c3200ed3373a210 Mon Sep 17 00:00:00 2001 From: Camelid Date: Tue, 27 Apr 2021 17:11:58 -0700 Subject: [PATCH 13/15] Add note to docs when layout cannot be computed This should prevent confusion about why generic types don't have layout docs. --- src/librustdoc/html/render/print_item.rs | 33 +++++++++++++++++++----- src/test/rustdoc/type-layout.rs | 10 ++++++- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index af7745d6126c9..bde42371713ca 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -7,6 +7,7 @@ use rustc_hir as hir; use rustc_hir::def::CtorKind; use rustc_hir::def_id::DefId; use rustc_middle::middle::stability; +use rustc_middle::ty::layout::LayoutError; use rustc_middle::ty::TyCtxt; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Symbol}; @@ -1540,13 +1541,14 @@ fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) { return; } + writeln!(w, "

Layout

"); + writeln!(w, "
"); + let tcx = cx.tcx(); let param_env = tcx.param_env(ty_def_id); let ty = tcx.type_of(ty_def_id); match tcx.layout_of(param_env.and(ty)) { Ok(ty_layout) => { - writeln!(w, "

Layout

"); - writeln!(w, "
"); writeln!( w, "

Note: Most layout information is \ @@ -1567,11 +1569,28 @@ fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) { pl = if bytes == 1 { "" } else { "s" }, ); } - writeln!(w, "

"); } - // Layout errors can occur with valid code, e.g. if you try to get the layout - // of a generic type such as `Vec`. In case of a layout error, we just - // don't show any layout information. - Err(_) => {} + // This kind of layout error can occur with valid code, e.g. if you try to + // get the layout of a generic type such as `Vec`. + Err(LayoutError::Unknown(_)) => { + writeln!( + w, + "

Note: Unable to compute type layout, \ + possibly due to this type having generic parameters. \ + Layout can only be computed for concrete, fully-instantiated types.

" + ); + } + // This kind of error probably can't happen with valid code, but we don't + // want to panic and prevent the docs from building, so we just let the + // user know that we couldn't compute the layout. + Err(LayoutError::SizeOverflow(_)) => { + writeln!( + w, + "

Note: Encountered an error during type layout; \ + the type was too big.

" + ); + } } + + writeln!(w, "
"); } diff --git a/src/test/rustdoc/type-layout.rs b/src/test/rustdoc/type-layout.rs index cb6e354f7df54..637e4aef3d61c 100644 --- a/src/test/rustdoc/type-layout.rs +++ b/src/test/rustdoc/type-layout.rs @@ -35,9 +35,17 @@ pub struct Y(u8); // @has - '0 bytes' pub struct Z; -// @!has type_layout/struct.Generic.html 'Size: ' +// We can't compute layout for generic types. +// @has type_layout/struct.Generic.html 'Unable to compute type layout, possibly due to this type having generic parameters' +// @!has - 'Size: ' pub struct Generic(T); +// We *can*, however, compute layout for types that are only generic over lifetimes, +// because lifetimes are a type-system construct. +// @has type_layout/struct.GenericLifetimes.html 'Size: ' +// @has - ' bytes' +pub struct GenericLifetimes<'a>(&'a str); + // @has type_layout/struct.Unsized.html 'Size: ' // @has - '(unsized)' pub struct Unsized([u8]); From 9b89d01bbbc674f19a69838d2eb2e17ba4a84899 Mon Sep 17 00:00:00 2001 From: Camelid Date: Sun, 9 May 2021 13:15:33 -0700 Subject: [PATCH 14/15] Enable `--show-type-layout` for the rustdoc API docs --- src/bootstrap/doc.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index e42d4fcd8647c..326a6fdaa80ff 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -649,6 +649,7 @@ impl Step for Rustdoc { cargo.rustdocflag("--document-private-items"); cargo.rustdocflag("--enable-index-page"); + cargo.rustdocflag("--show-type-layout"); cargo.rustdocflag("-Zunstable-options"); builder.run(&mut cargo.into()); } From d43701caa01003d9e0386fbd7a61d530e830564b Mon Sep 17 00:00:00 2001 From: Camelid Date: Sun, 9 May 2021 13:18:28 -0700 Subject: [PATCH 15/15] Disable layout docs for type aliases for now There are issues with computing layout for type aliases; see #85103. Once the issues are fixed, we should re-enable layout docs for them. --- src/librustdoc/html/render/print_item.rs | 2 -- src/test/rustdoc/type-layout.rs | 4 ---- 2 files changed, 6 deletions(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index bde42371713ca..f0ca24b8f0221 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -837,8 +837,6 @@ fn item_typedef(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::T // associated items from the aliased type (see discussion in #32077), but // we need #14072 to make sense of the generics. render_assoc_items(w, cx, it, def_id, AssocItemRender::All); - - document_type_layout(w, cx, def_id); } fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Union) { diff --git a/src/test/rustdoc/type-layout.rs b/src/test/rustdoc/type-layout.rs index 637e4aef3d61c..272911de6815b 100644 --- a/src/test/rustdoc/type-layout.rs +++ b/src/test/rustdoc/type-layout.rs @@ -50,9 +50,5 @@ pub struct GenericLifetimes<'a>(&'a str); // @has - '(unsized)' pub struct Unsized([u8]); -// @has type_layout/type.TypeAlias.html 'Size: ' -// @has - ' bytes' -pub type TypeAlias = X; - // @!has type_layout/trait.MyTrait.html 'Size: ' pub trait MyTrait {}