-
Notifications
You must be signed in to change notification settings - Fork 13.3k
rustdoc: migrate document_type_layout
to askama
#109949
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
08f204e
5f9746b
3a16db1
e26ae95
99e1cdb
2b728c1
e6664c0
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 |
---|---|---|
@@ -0,0 +1,86 @@ | ||
use askama::Template; | ||
|
||
use rustc_data_structures::captures::Captures; | ||
use rustc_hir::def_id::DefId; | ||
use rustc_middle::span_bug; | ||
use rustc_middle::ty::layout::LayoutError; | ||
use rustc_middle::ty::Adt; | ||
use rustc_span::symbol::Symbol; | ||
use rustc_target::abi::{Primitive, TagEncoding, Variants}; | ||
|
||
use std::fmt; | ||
|
||
use crate::html::format::display_fn; | ||
use crate::html::render::Context; | ||
|
||
#[derive(Template)] | ||
#[template(path = "type_layout.html")] | ||
struct TypeLayout<'cx> { | ||
variants: Vec<(Symbol, TypeLayoutSize)>, | ||
type_layout_size: Result<TypeLayoutSize, LayoutError<'cx>>, | ||
} | ||
|
||
#[derive(Template)] | ||
#[template(path = "type_layout_size.html")] | ||
struct TypeLayoutSize { | ||
is_unsized: bool, | ||
is_uninhabited: bool, | ||
size: u64, | ||
} | ||
|
||
pub(crate) fn document_type_layout<'a, 'cx: 'a>( | ||
cx: &'a Context<'cx>, | ||
ty_def_id: DefId, | ||
) -> impl fmt::Display + 'a + Captures<'cx> { | ||
display_fn(move |f| { | ||
if !cx.shared.show_type_layout { | ||
return Ok(()); | ||
} | ||
|
||
let tcx = cx.tcx(); | ||
let param_env = tcx.param_env(ty_def_id); | ||
let ty = tcx.type_of(ty_def_id).subst_identity(); | ||
let type_layout = tcx.layout_of(param_env.and(ty)); | ||
|
||
let variants = | ||
if let Ok(type_layout) = type_layout && | ||
let Variants::Multiple { variants, tag, tag_encoding, .. } = | ||
type_layout.layout.variants() && | ||
!variants.is_empty() | ||
{ | ||
let tag_size = | ||
if let TagEncoding::Niche { .. } = tag_encoding { | ||
0 | ||
} else if let Primitive::Int(i, _) = tag.primitive() { | ||
i.size().bytes() | ||
} else { | ||
span_bug!(cx.tcx().def_span(ty_def_id), "tag is neither niche nor int") | ||
}; | ||
variants | ||
.iter_enumerated() | ||
.map(|(variant_idx, variant_layout)| { | ||
let Adt(adt, _) = type_layout.ty.kind() else { | ||
span_bug!(cx.tcx().def_span(ty_def_id), "not an adt") | ||
}; | ||
let name = adt.variant(variant_idx).name; | ||
let is_unsized = variant_layout.abi.is_unsized(); | ||
let is_uninhabited = variant_layout.abi.is_uninhabited(); | ||
let size = variant_layout.size.bytes() - tag_size; | ||
let type_layout_size = TypeLayoutSize { is_unsized, is_uninhabited, size }; | ||
(name, type_layout_size) | ||
}) | ||
.collect() | ||
} else { | ||
Vec::new() | ||
}; | ||
|
||
let type_layout_size = tcx.layout_of(param_env.and(ty)).map(|layout| { | ||
let is_unsized = layout.abi.is_unsized(); | ||
let is_uninhabited = layout.abi.is_uninhabited(); | ||
let size = layout.size.bytes(); | ||
TypeLayoutSize { is_unsized, is_uninhabited, size } | ||
}); | ||
|
||
Ok(TypeLayout { variants, type_layout_size }.render_into(f).unwrap()) | ||
}) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
<h2 id="layout" class="small-section-header"> {# #} | ||
Layout<a href="#layout" class="anchor">§</a> {# #} | ||
</h2> {# #} | ||
<div class="docblock"> {# #} | ||
{% match type_layout_size %} | ||
{% when Ok(type_layout_size) %} | ||
<div class="warning"> {# #} | ||
<p> {# #} | ||
<strong>Note:</strong> Most layout information is <strong>completely {#+ #} | ||
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. According to Askama's docs, the 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. If it was |
||
unstable</strong> and may even differ between compilations. {#+ #} | ||
The only exception is types with certain <code>repr(...)</code> {#+ #} | ||
attributes. Please see the Rust Reference’s {#+ #} | ||
<a href="https://doc.rust-lang.org/reference/type-layout.html">“Type Layout”</a> {#+ #} | ||
chapter for details on type layout guarantees. {# #} | ||
</p> {# #} | ||
</div> {# #} | ||
<p><strong>Size:</strong> {{ type_layout_size|safe }}</p> {# #} | ||
{% if !variants.is_empty() %} | ||
<p> {# #} | ||
<strong>Size for each variant:</strong> {# #} | ||
</p> {# #} | ||
<ul> {# #} | ||
{% for (name, layout_size) in variants %} | ||
<li> {# #} | ||
<code>{{ name }}</code>: {#+ #} | ||
{{ layout_size|safe }} | ||
</li> {# #} | ||
{% endfor %} | ||
</ul> {# #} | ||
{% endif %} | ||
{# 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<T>`. #} | ||
{% when Err(LayoutError::Unknown(_)) %} | ||
<p> {# #} | ||
<strong>Note:</strong> Unable to compute type layout, {#+ #} | ||
possibly due to this type having generic parameters. {#+ #} | ||
Layout can only be computed for concrete, fully-instantiated types. {# #} | ||
</p> {# #} | ||
{# 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. #} | ||
{% when Err(LayoutError::SizeOverflow(_)) %} | ||
<p> {# #} | ||
<strong>Note:</strong> Encountered an error during type layout; {#+ #} | ||
the type was too big. {# #} | ||
</p> {# #} | ||
{% when Err(LayoutError::NormalizationFailure(_, _)) %} | ||
<p> {# #} | ||
<strong>Note:</strong> Encountered an error during type layout; {#+ #} | ||
the type failed to be normalized. {# #} | ||
</p> {# #} | ||
{% endmatch %} | ||
</div> {# #} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{% if is_unsized %} | ||
(unsized) | ||
{% else %} | ||
{% if size == 1 %} | ||
1 byte | ||
{% else %} | ||
{{ size +}} bytes | ||
{% endif %} | ||
{% if is_uninhabited %} | ||
{# +#} (<a href="https://doc.rust-lang.org/stable/reference/glossary.html#uninhabited">uninhabited</a>) | ||
{% endif %} | ||
{% endif %} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the meaning of the
{# #}
here and below? According to Askama's docs, it's a block comment?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a block comment, yes.
The point of it is to eat the whitespace between the end of this tag and the start of the one on the next line (it would normally be preserved).