From aff4cd5ce725602249c2554b04b1066d09acd31e Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Mon, 14 Jun 2021 01:49:37 +0800 Subject: [PATCH 1/5] Report Layout of enum variants Followup of #83501, Fixes #86253. --- src/librustdoc/html/render/print_item.rs | 36 +++++++++++++++++++++++- src/test/rustdoc/type-layout.rs | 6 ++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 8f4857a693928..f362a288bcbf9 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -7,11 +7,13 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; use rustc_hir::def::CtorKind; use rustc_hir::def_id::DefId; +use rustc_middle::bug; use rustc_middle::middle::stability; use rustc_middle::ty::layout::LayoutError; -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::{Adt, TyCtxt}; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Symbol}; +use rustc_target::abi::Variants; use super::{ collect_paths_for_type, document, ensure_trailing_slash, item_ty_to_strs, notable_traits_decl, @@ -1636,6 +1638,38 @@ fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) { pl = if bytes == 1 { "" } else { "s" }, ); } + if let Variants::Multiple { variants, .. } = &ty_layout.layout.variants { + if !variants.is_empty() { + w.write_str( + "

\ + Size for each variant:\ +

"); + } + } } // 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`. diff --git a/src/test/rustdoc/type-layout.rs b/src/test/rustdoc/type-layout.rs index 272911de6815b..f398dd776d9c6 100644 --- a/src/test/rustdoc/type-layout.rs +++ b/src/test/rustdoc/type-layout.rs @@ -52,3 +52,9 @@ pub struct Unsized([u8]); // @!has type_layout/trait.MyTrait.html 'Size: ' pub trait MyTrait {} + +// @has type_layout/enum.Variants.html '1 byte' +pub enum Variants { + A, + B(u8), +} From c349b79029770e39963fadf5021cfa6a6cfe5472 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Fri, 9 Jul 2021 22:25:46 +0800 Subject: [PATCH 2/5] Apply suggestions --- src/librustdoc/html/render/print_item.rs | 44 ++++++++++-------------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index f362a288bcbf9..b25323c4e0a74 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -7,13 +7,13 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; use rustc_hir::def::CtorKind; use rustc_hir::def_id::DefId; -use rustc_middle::bug; use rustc_middle::middle::stability; +use rustc_middle::span_bug; use rustc_middle::ty::layout::LayoutError; use rustc_middle::ty::{Adt, TyCtxt}; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Symbol}; -use rustc_target::abi::Variants; +use rustc_target::abi::{Layout, Variants}; use super::{ collect_paths_for_type, document, ensure_trailing_slash, item_ty_to_strs, notable_traits_decl, @@ -1606,6 +1606,15 @@ fn document_non_exhaustive(w: &mut Buffer, item: &clean::Item) { } fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) { + fn write_size_of_layout(w: &mut Buffer, layout: &Layout) { + if layout.abi.is_unsized() { + write!(w, "(unsized)"); + } else { + let bytes = layout.size.bytes(); + write!(w, "{size} byte{pl}", size = bytes, pl = if bytes == 1 { "" } else { "s" },); + } + } + if !cx.shared.show_type_layout { return; } @@ -1627,17 +1636,9 @@ fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) { “Type Layout” \ chapter for details on type layout guarantees.

" ); - 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 = bytes, - pl = if bytes == 1 { "" } else { "s" }, - ); - } + w.write_str("

Size: "); + write_size_of_layout(w, ty_layout.layout); + writeln!(w, "

"); if let Variants::Multiple { variants, .. } = &ty_layout.layout.variants { if !variants.is_empty() { w.write_str( @@ -1649,23 +1650,14 @@ fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) { let adt = if let Adt(adt, _) = ty_layout.ty.kind() { adt } else { - bug!("not an adt") + span_bug!(tcx.def_span(ty_def_id), "not an adt") }; for (index, layout) in variants.iter_enumerated() { let ident = adt.variants[index].ident; - if layout.abi.is_unsized() { - writeln!(w, "
  • {name} (unsized)
  • ", name = ident); - } else { - let bytes = layout.size.bytes(); - writeln!( - w, - "
  • {name}: {size} byte{pl}
  • ", - name = ident, - size = bytes, - pl = if bytes == 1 { "" } else { "s" }, - ); - } + write!(w, "
  • {name} ", name = ident); + write_size_of_layout(w, layout); + writeln!(w, "
  • "); } w.write_str("

    "); } From 8096910b54920f4c3334de555ee9dd265ed6f49d Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Sat, 10 Jul 2021 21:35:40 +0800 Subject: [PATCH 3/5] Report variant size without the discriminant --- src/librustdoc/html/render/print_item.rs | 20 +++++++++++++------- src/test/rustdoc/type-layout.rs | 3 ++- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index b25323c4e0a74..4e90e611a16ae 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -13,7 +13,7 @@ use rustc_middle::ty::layout::LayoutError; use rustc_middle::ty::{Adt, TyCtxt}; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Symbol}; -use rustc_target::abi::{Layout, Variants}; +use rustc_target::abi::{Layout, Primitive, Variants}; use super::{ collect_paths_for_type, document, ensure_trailing_slash, item_ty_to_strs, notable_traits_decl, @@ -1606,11 +1606,11 @@ fn document_non_exhaustive(w: &mut Buffer, item: &clean::Item) { } fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) { - fn write_size_of_layout(w: &mut Buffer, layout: &Layout) { + fn write_size_of_layout(w: &mut Buffer, layout: &Layout, tag_size: u64) { if layout.abi.is_unsized() { write!(w, "(unsized)"); } else { - let bytes = layout.size.bytes(); + let bytes = layout.size.bytes() - tag_size; write!(w, "{size} byte{pl}", size = bytes, pl = if bytes == 1 { "" } else { "s" },); } } @@ -1637,9 +1637,9 @@ fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) { chapter for details on type layout guarantees.

    " ); w.write_str("

    Size: "); - write_size_of_layout(w, ty_layout.layout); + write_size_of_layout(w, ty_layout.layout, 0); writeln!(w, "

    "); - if let Variants::Multiple { variants, .. } = &ty_layout.layout.variants { + if let Variants::Multiple { variants, tag, .. } = &ty_layout.layout.variants { if !variants.is_empty() { w.write_str( "

    \ @@ -1653,10 +1653,16 @@ fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) { span_bug!(tcx.def_span(ty_def_id), "not an adt") }; + let tag_size = if let Primitive::Int(i, _) = tag.value { + i.size().bytes() + } else { + span_bug!(tcx.def_span(ty_def_id), "tag is not int") + }; + for (index, layout) in variants.iter_enumerated() { let ident = adt.variants[index].ident; - write!(w, "

  • {name} ", name = ident); - write_size_of_layout(w, layout); + write!(w, "
  • {name}: ", name = ident); + write_size_of_layout(w, layout, tag_size); writeln!(w, "
  • "); } w.write_str("

    "); diff --git a/src/test/rustdoc/type-layout.rs b/src/test/rustdoc/type-layout.rs index f398dd776d9c6..bc1b65c46e24a 100644 --- a/src/test/rustdoc/type-layout.rs +++ b/src/test/rustdoc/type-layout.rs @@ -53,7 +53,8 @@ pub struct Unsized([u8]); // @!has type_layout/trait.MyTrait.html 'Size: ' pub trait MyTrait {} -// @has type_layout/enum.Variants.html '1 byte' +// @has type_layout/enum.Variants.html 'A: 0 bytes' +// @has - 'B: 1 byte' pub enum Variants { A, B(u8), From 5f1505e7f13fdea3f2d626059010cf26edfce4f8 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Tue, 31 Aug 2021 05:24:08 +0000 Subject: [PATCH 4/5] Apply suggestions --- src/librustdoc/html/render/print_item.rs | 5 ++--- src/test/rustdoc/type-layout.rs | 4 +++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 4e90e611a16ae..6054073bf79b2 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1642,8 +1642,7 @@ fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) { if let Variants::Multiple { variants, tag, .. } = &ty_layout.layout.variants { if !variants.is_empty() { w.write_str( - "

    \ - Size for each variant:\ + "

    Size for each variant:

    \
      ", ); @@ -1665,7 +1664,7 @@ fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) { write_size_of_layout(w, layout, tag_size); writeln!(w, ""); } - w.write_str("

    "); + w.write_str(""); } } } diff --git a/src/test/rustdoc/type-layout.rs b/src/test/rustdoc/type-layout.rs index bc1b65c46e24a..8c4f4f8fc98e6 100644 --- a/src/test/rustdoc/type-layout.rs +++ b/src/test/rustdoc/type-layout.rs @@ -53,7 +53,9 @@ pub struct Unsized([u8]); // @!has type_layout/trait.MyTrait.html 'Size: ' pub trait MyTrait {} -// @has type_layout/enum.Variants.html 'A: 0 bytes' +// @has type_layout/enum.Variants.html 'Size: ' +// @has - '2 bytes' +// @has - 'A: 0 bytes' // @has - 'B: 1 byte' pub enum Variants { A, From c0451f73b2094d7edccb77d7ea8be48f64887e67 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Mon, 6 Sep 2021 07:09:32 +0000 Subject: [PATCH 5/5] Correctly handle niche of enum --- src/librustdoc/html/render/print_item.rs | 12 ++++++++---- src/test/rustdoc/type-layout.rs | 9 +++++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 6054073bf79b2..aac631a1cfcdd 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -13,7 +13,7 @@ use rustc_middle::ty::layout::LayoutError; use rustc_middle::ty::{Adt, TyCtxt}; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Symbol}; -use rustc_target::abi::{Layout, Primitive, Variants}; +use rustc_target::abi::{Layout, Primitive, TagEncoding, Variants}; use super::{ collect_paths_for_type, document, ensure_trailing_slash, item_ty_to_strs, notable_traits_decl, @@ -1639,7 +1639,9 @@ fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) { w.write_str("

    Size: "); write_size_of_layout(w, ty_layout.layout, 0); writeln!(w, "

    "); - if let Variants::Multiple { variants, tag, .. } = &ty_layout.layout.variants { + if let Variants::Multiple { variants, tag, tag_encoding, .. } = + &ty_layout.layout.variants + { if !variants.is_empty() { w.write_str( "

    Size for each variant:

    \ @@ -1652,10 +1654,12 @@ fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) { span_bug!(tcx.def_span(ty_def_id), "not an adt") }; - let tag_size = if let Primitive::Int(i, _) = tag.value { + let tag_size = if let TagEncoding::Niche { .. } = tag_encoding { + 0 + } else if let Primitive::Int(i, _) = tag.value { i.size().bytes() } else { - span_bug!(tcx.def_span(ty_def_id), "tag is not int") + span_bug!(tcx.def_span(ty_def_id), "tag is neither niche nor int") }; for (index, layout) in variants.iter_enumerated() { diff --git a/src/test/rustdoc/type-layout.rs b/src/test/rustdoc/type-layout.rs index 8c4f4f8fc98e6..0868486fa59cd 100644 --- a/src/test/rustdoc/type-layout.rs +++ b/src/test/rustdoc/type-layout.rs @@ -61,3 +61,12 @@ pub enum Variants { A, B(u8), } + +// @has type_layout/enum.WithNiche.html 'Size: ' +// @has - //p '4 bytes' +// @has - 'None: 0 bytes' +// @has - 'Some: 4 bytes' +pub enum WithNiche { + None, + Some(std::num::NonZeroU32), +}