-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Rustdoc: Report Layout of enum variants #86263
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,10 +8,12 @@ use rustc_hir as hir; | |
use rustc_hir::def::CtorKind; | ||
use rustc_hir::def_id::DefId; | ||
use rustc_middle::middle::stability; | ||
use rustc_middle::span_bug; | ||
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::{Layout, Primitive, TagEncoding, Variants}; | ||
|
||
use super::{ | ||
collect_paths_for_type, document, ensure_trailing_slash, item_ty_to_strs, notable_traits_decl, | ||
|
@@ -1604,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, tag_size: u64) { | ||
if layout.abi.is_unsized() { | ||
write!(w, "(unsized)"); | ||
} else { | ||
let bytes = layout.size.bytes() - tag_size; | ||
write!(w, "{size} byte{pl}", size = bytes, pl = if bytes == 1 { "" } else { "s" },); | ||
} | ||
} | ||
|
||
if !cx.shared.show_type_layout { | ||
return; | ||
} | ||
|
@@ -1625,16 +1636,40 @@ fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) { | |
<a href=\"https://doc.rust-lang.org/reference/type-layout.html\">“Type Layout”</a> \ | ||
chapter for details on type layout guarantees.</p></div>" | ||
); | ||
if ty_layout.layout.abi.is_unsized() { | ||
writeln!(w, "<p><strong>Size:</strong> (unsized)</p>"); | ||
} else { | ||
let bytes = ty_layout.layout.size.bytes(); | ||
writeln!( | ||
w, | ||
"<p><strong>Size:</strong> {size} byte{pl}</p>", | ||
size = bytes, | ||
pl = if bytes == 1 { "" } else { "s" }, | ||
); | ||
w.write_str("<p><strong>Size:</strong> "); | ||
write_size_of_layout(w, ty_layout.layout, 0); | ||
writeln!(w, "</p>"); | ||
if let Variants::Multiple { variants, tag, tag_encoding, .. } = | ||
&ty_layout.layout.variants | ||
{ | ||
if !variants.is_empty() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you test what happens for the empty case? Does it show 0 bytes or unsized? I think ideally it would show "uninhabited" or something. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It shows 0 bytes. I think it would be more suitable for a separate PR as a followup of the original PR. |
||
w.write_str( | ||
"<p><strong>Size for each variant:</strong></p>\ | ||
<ul>", | ||
); | ||
|
||
let adt = if let Adt(adt, _) = ty_layout.ty.kind() { | ||
adt | ||
} else { | ||
span_bug!(tcx.def_span(ty_def_id), "not an adt") | ||
}; | ||
|
||
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 neither niche nor int") | ||
}; | ||
|
||
for (index, layout) in variants.iter_enumerated() { | ||
let ident = adt.variants[index].ident; | ||
write!(w, "<li><code>{name}</code>: ", name = ident); | ||
write_size_of_layout(w, layout, tag_size); | ||
writeln!(w, "</li>"); | ||
} | ||
fee1-dead marked this conversation as resolved.
Show resolved
Hide resolved
|
||
w.write_str("</ul>"); | ||
} | ||
} | ||
} | ||
// This kind of layout error can occur with valid code, e.g. if you try to | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -52,3 +52,21 @@ pub struct Unsized([u8]); | |
|
||
// @!has type_layout/trait.MyTrait.html 'Size: ' | ||
pub trait MyTrait {} | ||
|
||
// @has type_layout/enum.Variants.html 'Size: ' | ||
// @has - '2 bytes' | ||
// @has - '<code>A</code>: 0 bytes' | ||
// @has - '<code>B</code>: 1 byte' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just to confirm: this checks that this "text" is in the raw HTML directly, right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's odd is I tried |
||
pub enum Variants { | ||
A, | ||
B(u8), | ||
} | ||
fee1-dead marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// @has type_layout/enum.WithNiche.html 'Size: ' | ||
// @has - //p '4 bytes' | ||
// @has - '<code>None</code>: 0 bytes' | ||
// @has - '<code>Some</code>: 4 bytes' | ||
pub enum WithNiche { | ||
None, | ||
Some(std::num::NonZeroU32), | ||
} |
Uh oh!
There was an error while loading. Please reload this page.