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:\
+
",
+ );
+
+ let adt = if let Adt(adt, _) = ty_layout.ty.kind() {
+ adt
+ } else {
+ bug!("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" },
+ );
+ }
+ }
+ w.write_str("
");
+ }
+ }
}
// 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),
+}