Skip to content

Commit 684bdf8

Browse files
authored
Rollup merge of #109949 - notriddle:notriddle/type-layout, r=jsha
rustdoc: migrate `document_type_layout` to askama
2 parents 0fd50f3 + e6664c0 commit 684bdf8

File tree

5 files changed

+154
-116
lines changed

5 files changed

+154
-116
lines changed

src/librustdoc/html/render/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ mod context;
3232
mod print_item;
3333
mod sidebar;
3434
mod span_map;
35+
mod type_layout;
3536
mod write_shared;
3637

3738
pub(crate) use self::context::*;

src/librustdoc/html/render/print_item.rs

+2-116
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,14 @@ use rustc_hir as hir;
66
use rustc_hir::def::CtorKind;
77
use rustc_hir::def_id::DefId;
88
use rustc_middle::middle::stability;
9-
use rustc_middle::span_bug;
10-
use rustc_middle::ty::layout::LayoutError;
11-
use rustc_middle::ty::{self, Adt, TyCtxt};
9+
use rustc_middle::ty::{self, TyCtxt};
1210
use rustc_span::hygiene::MacroKind;
1311
use rustc_span::symbol::{kw, sym, Symbol};
14-
use rustc_target::abi::{LayoutS, Primitive, TagEncoding, Variants};
1512
use std::cmp::Ordering;
1613
use std::fmt;
1714
use std::rc::Rc;
1815

16+
use super::type_layout::document_type_layout;
1917
use super::{
2018
collect_paths_for_type, document, ensure_trailing_slash, get_filtered_impls_for_reference,
2119
item_ty_to_section, notable_traits_button, notable_traits_json, render_all_impls,
@@ -1933,118 +1931,6 @@ fn document_non_exhaustive<'a>(item: &'a clean::Item) -> impl fmt::Display + 'a
19331931
})
19341932
}
19351933

1936-
fn document_type_layout<'a, 'cx: 'a>(
1937-
cx: &'a Context<'cx>,
1938-
ty_def_id: DefId,
1939-
) -> impl fmt::Display + 'a + Captures<'cx> {
1940-
fn write_size_of_layout(mut w: impl fmt::Write, layout: &LayoutS, tag_size: u64) {
1941-
if layout.abi.is_unsized() {
1942-
write!(w, "(unsized)").unwrap();
1943-
} else {
1944-
let size = layout.size.bytes() - tag_size;
1945-
write!(w, "{size} byte{pl}", pl = if size == 1 { "" } else { "s" }).unwrap();
1946-
if layout.abi.is_uninhabited() {
1947-
write!(
1948-
w,
1949-
" (<a href=\"https://doc.rust-lang.org/stable/reference/glossary.html#uninhabited\">uninhabited</a>)"
1950-
).unwrap();
1951-
}
1952-
}
1953-
}
1954-
1955-
display_fn(move |mut f| {
1956-
if !cx.shared.show_type_layout {
1957-
return Ok(());
1958-
}
1959-
1960-
writeln!(
1961-
f,
1962-
"<h2 id=\"layout\" class=\"small-section-header\"> \
1963-
Layout<a href=\"#layout\" class=\"anchor\">§</a></h2>"
1964-
)?;
1965-
writeln!(f, "<div class=\"docblock\">")?;
1966-
1967-
let tcx = cx.tcx();
1968-
let param_env = tcx.param_env(ty_def_id);
1969-
let ty = tcx.type_of(ty_def_id).subst_identity();
1970-
match tcx.layout_of(param_env.and(ty)) {
1971-
Ok(ty_layout) => {
1972-
writeln!(
1973-
f,
1974-
"<div class=\"warning\"><p><strong>Note:</strong> Most layout information is \
1975-
<strong>completely unstable</strong> and may even differ between compilations. \
1976-
The only exception is types with certain <code>repr(...)</code> attributes. \
1977-
Please see the Rust Reference’s \
1978-
<a href=\"https://doc.rust-lang.org/reference/type-layout.html\">“Type Layout”</a> \
1979-
chapter for details on type layout guarantees.</p></div>"
1980-
)?;
1981-
f.write_str("<p><strong>Size:</strong> ")?;
1982-
write_size_of_layout(&mut f, &ty_layout.layout.0, 0);
1983-
writeln!(f, "</p>")?;
1984-
if let Variants::Multiple { variants, tag, tag_encoding, .. } =
1985-
&ty_layout.layout.variants()
1986-
{
1987-
if !variants.is_empty() {
1988-
f.write_str(
1989-
"<p><strong>Size for each variant:</strong></p>\
1990-
<ul>",
1991-
)?;
1992-
1993-
let Adt(adt, _) = ty_layout.ty.kind() else {
1994-
span_bug!(tcx.def_span(ty_def_id), "not an adt")
1995-
};
1996-
1997-
let tag_size = if let TagEncoding::Niche { .. } = tag_encoding {
1998-
0
1999-
} else if let Primitive::Int(i, _) = tag.primitive() {
2000-
i.size().bytes()
2001-
} else {
2002-
span_bug!(tcx.def_span(ty_def_id), "tag is neither niche nor int")
2003-
};
2004-
2005-
for (index, layout) in variants.iter_enumerated() {
2006-
let name = adt.variant(index).name;
2007-
write!(&mut f, "<li><code>{name}</code>: ")?;
2008-
write_size_of_layout(&mut f, layout, tag_size);
2009-
writeln!(&mut f, "</li>")?;
2010-
}
2011-
f.write_str("</ul>")?;
2012-
}
2013-
}
2014-
}
2015-
// This kind of layout error can occur with valid code, e.g. if you try to
2016-
// get the layout of a generic type such as `Vec<T>`.
2017-
Err(LayoutError::Unknown(_)) => {
2018-
writeln!(
2019-
f,
2020-
"<p><strong>Note:</strong> Unable to compute type layout, \
2021-
possibly due to this type having generic parameters. \
2022-
Layout can only be computed for concrete, fully-instantiated types.</p>"
2023-
)?;
2024-
}
2025-
// This kind of error probably can't happen with valid code, but we don't
2026-
// want to panic and prevent the docs from building, so we just let the
2027-
// user know that we couldn't compute the layout.
2028-
Err(LayoutError::SizeOverflow(_)) => {
2029-
writeln!(
2030-
f,
2031-
"<p><strong>Note:</strong> Encountered an error during type layout; \
2032-
the type was too big.</p>"
2033-
)?;
2034-
}
2035-
Err(LayoutError::NormalizationFailure(_, _)) => {
2036-
writeln!(
2037-
f,
2038-
"<p><strong>Note:</strong> Encountered an error during type layout; \
2039-
the type failed to be normalized.</p>"
2040-
)?;
2041-
}
2042-
}
2043-
2044-
writeln!(f, "</div>")
2045-
})
2046-
}
2047-
20481934
fn pluralize(count: usize) -> &'static str {
20491935
if count > 1 { "s" } else { "" }
20501936
}
+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
use askama::Template;
2+
3+
use rustc_data_structures::captures::Captures;
4+
use rustc_hir::def_id::DefId;
5+
use rustc_middle::span_bug;
6+
use rustc_middle::ty::layout::LayoutError;
7+
use rustc_middle::ty::Adt;
8+
use rustc_span::symbol::Symbol;
9+
use rustc_target::abi::{Primitive, TagEncoding, Variants};
10+
11+
use std::fmt;
12+
13+
use crate::html::format::display_fn;
14+
use crate::html::render::Context;
15+
16+
#[derive(Template)]
17+
#[template(path = "type_layout.html")]
18+
struct TypeLayout<'cx> {
19+
variants: Vec<(Symbol, TypeLayoutSize)>,
20+
type_layout_size: Result<TypeLayoutSize, LayoutError<'cx>>,
21+
}
22+
23+
#[derive(Template)]
24+
#[template(path = "type_layout_size.html")]
25+
struct TypeLayoutSize {
26+
is_unsized: bool,
27+
is_uninhabited: bool,
28+
size: u64,
29+
}
30+
31+
pub(crate) fn document_type_layout<'a, 'cx: 'a>(
32+
cx: &'a Context<'cx>,
33+
ty_def_id: DefId,
34+
) -> impl fmt::Display + 'a + Captures<'cx> {
35+
display_fn(move |f| {
36+
if !cx.shared.show_type_layout {
37+
return Ok(());
38+
}
39+
40+
let tcx = cx.tcx();
41+
let param_env = tcx.param_env(ty_def_id);
42+
let ty = tcx.type_of(ty_def_id).subst_identity();
43+
let type_layout = tcx.layout_of(param_env.and(ty));
44+
45+
let variants =
46+
if let Ok(type_layout) = type_layout &&
47+
let Variants::Multiple { variants, tag, tag_encoding, .. } =
48+
type_layout.layout.variants() &&
49+
!variants.is_empty()
50+
{
51+
let tag_size =
52+
if let TagEncoding::Niche { .. } = tag_encoding {
53+
0
54+
} else if let Primitive::Int(i, _) = tag.primitive() {
55+
i.size().bytes()
56+
} else {
57+
span_bug!(cx.tcx().def_span(ty_def_id), "tag is neither niche nor int")
58+
};
59+
variants
60+
.iter_enumerated()
61+
.map(|(variant_idx, variant_layout)| {
62+
let Adt(adt, _) = type_layout.ty.kind() else {
63+
span_bug!(cx.tcx().def_span(ty_def_id), "not an adt")
64+
};
65+
let name = adt.variant(variant_idx).name;
66+
let is_unsized = variant_layout.abi.is_unsized();
67+
let is_uninhabited = variant_layout.abi.is_uninhabited();
68+
let size = variant_layout.size.bytes() - tag_size;
69+
let type_layout_size = TypeLayoutSize { is_unsized, is_uninhabited, size };
70+
(name, type_layout_size)
71+
})
72+
.collect()
73+
} else {
74+
Vec::new()
75+
};
76+
77+
let type_layout_size = tcx.layout_of(param_env.and(ty)).map(|layout| {
78+
let is_unsized = layout.abi.is_unsized();
79+
let is_uninhabited = layout.abi.is_uninhabited();
80+
let size = layout.size.bytes();
81+
TypeLayoutSize { is_unsized, is_uninhabited, size }
82+
});
83+
84+
Ok(TypeLayout { variants, type_layout_size }.render_into(f).unwrap())
85+
})
86+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<h2 id="layout" class="small-section-header"> {# #}
2+
Layout<a href="#layout" class="anchor">§</a> {# #}
3+
</h2> {# #}
4+
<div class="docblock"> {# #}
5+
{% match type_layout_size %}
6+
{% when Ok(type_layout_size) %}
7+
<div class="warning"> {# #}
8+
<p> {# #}
9+
<strong>Note:</strong> Most layout information is <strong>completely {#+ #}
10+
unstable</strong> and may even differ between compilations. {#+ #}
11+
The only exception is types with certain <code>repr(...)</code> {#+ #}
12+
attributes. Please see the Rust Reference’s {#+ #}
13+
<a href="https://doc.rust-lang.org/reference/type-layout.html">“Type Layout”</a> {#+ #}
14+
chapter for details on type layout guarantees. {# #}
15+
</p> {# #}
16+
</div> {# #}
17+
<p><strong>Size:</strong> {{ type_layout_size|safe }}</p> {# #}
18+
{% if !variants.is_empty() %}
19+
<p> {# #}
20+
<strong>Size for each variant:</strong> {# #}
21+
</p> {# #}
22+
<ul> {# #}
23+
{% for (name, layout_size) in variants %}
24+
<li> {# #}
25+
<code>{{ name }}</code>: {#+ #}
26+
{{ layout_size|safe }}
27+
</li> {# #}
28+
{% endfor %}
29+
</ul> {# #}
30+
{% endif %}
31+
{# This kind of layout error can occur with valid code, e.g. if you try to
32+
get the layout of a generic type such as `Vec<T>`. #}
33+
{% when Err(LayoutError::Unknown(_)) %}
34+
<p> {# #}
35+
<strong>Note:</strong> Unable to compute type layout, {#+ #}
36+
possibly due to this type having generic parameters. {#+ #}
37+
Layout can only be computed for concrete, fully-instantiated types. {# #}
38+
</p> {# #}
39+
{# This kind of error probably can't happen with valid code, but we don't
40+
want to panic and prevent the docs from building, so we just let the
41+
user know that we couldn't compute the layout. #}
42+
{% when Err(LayoutError::SizeOverflow(_)) %}
43+
<p> {# #}
44+
<strong>Note:</strong> Encountered an error during type layout; {#+ #}
45+
the type was too big. {# #}
46+
</p> {# #}
47+
{% when Err(LayoutError::NormalizationFailure(_, _)) %}
48+
<p> {# #}
49+
<strong>Note:</strong> Encountered an error during type layout; {#+ #}
50+
the type failed to be normalized. {# #}
51+
</p> {# #}
52+
{% endmatch %}
53+
</div> {# #}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{% if is_unsized %}
2+
(unsized)
3+
{% else %}
4+
{% if size == 1 %}
5+
1 byte
6+
{% else %}
7+
{{ size +}} bytes
8+
{% endif %}
9+
{% if is_uninhabited %}
10+
{# +#} (<a href="https://doc.rust-lang.org/stable/reference/glossary.html#uninhabited">uninhabited</a>)
11+
{% endif %}
12+
{% endif %}

0 commit comments

Comments
 (0)