From 08f204e17f1f007d844743802e04d7f62689e966 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 4 Apr 2023 14:15:29 -0700 Subject: [PATCH 1/7] rustdoc: migrate `document_type_layout` to askama --- src/librustdoc/html/render/print_item.rs | 166 +++++++----------- .../html/templates/type_layout.html | 45 +++++ 2 files changed, 112 insertions(+), 99 deletions(-) create mode 100644 src/librustdoc/html/templates/type_layout.html diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 6bce57340040b..e089b55b9c4d1 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -5,13 +5,15 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir as hir; use rustc_hir::def::CtorKind; use rustc_hir::def_id::DefId; +use rustc_index::vec::IndexVec; use rustc_middle::middle::stability; use rustc_middle::span_bug; -use rustc_middle::ty::layout::LayoutError; +use rustc_middle::ty::layout::{LayoutError, TyAndLayout}; use rustc_middle::ty::{self, Adt, TyCtxt}; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Symbol}; -use rustc_target::abi::{LayoutS, Primitive, TagEncoding, Variants}; +use rustc_target::abi::{LayoutS, Primitive, TagEncoding, VariantIdx, Variants}; +use std::borrow::Borrow; use std::cmp::Ordering; use std::fmt; use std::rc::Rc; @@ -1936,111 +1938,77 @@ fn document_type_layout<'a, 'cx: 'a>( cx: &'a Context<'cx>, ty_def_id: DefId, ) -> impl fmt::Display + 'a + Captures<'cx> { - fn write_size_of_layout(mut w: impl fmt::Write, layout: &LayoutS, tag_size: u64) { - if layout.abi.is_unsized() { - write!(w, "(unsized)").unwrap(); - } else { - let size = layout.size.bytes() - tag_size; - write!(w, "{size} byte{pl}", pl = if size == 1 { "" } else { "s" }).unwrap(); - if layout.abi.is_uninhabited() { - write!( - w, - " (uninhabited)" - ).unwrap(); - } - } + #[derive(Template)] + #[template(path = "type_layout.html")] + struct TypeLayout<'a, 'cx> { + cx: &'a Context<'cx>, + ty_def_id: DefId, } - display_fn(move |mut f| { - if !cx.shared.show_type_layout { - return Ok(()); + impl<'a, 'cx: 'a> TypeLayout<'a, 'cx> { + fn variants<'b: 'a>(&'b self) -> Option<&'b IndexVec> { + if let Variants::Multiple { variants, .. } = + self.type_layout().unwrap().layout.variants() && !variants.is_empty() { + Some(&variants) + } else { + None + } } - - writeln!( - f, - "

\ - Layout§

" - )?; - writeln!(f, "
")?; - - let tcx = cx.tcx(); - let param_env = tcx.param_env(ty_def_id); - let ty = tcx.type_of(ty_def_id).subst_identity(); - match tcx.layout_of(param_env.and(ty)) { - Ok(ty_layout) => { - writeln!( - f, - "

Note: Most layout information is \ - completely unstable and may even differ between compilations. \ - The only exception is types with certain repr(...) attributes. \ - Please see the Rust Reference’s \ - “Type Layout” \ - chapter for details on type layout guarantees.

" - )?; - f.write_str("

Size: ")?; - write_size_of_layout(&mut f, &ty_layout.layout.0, 0); - writeln!(f, "

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

Size for each variant:

\ -
    ", + fn type_layout<'b: 'a>(&'b self) -> Result, LayoutError<'cx>> { + let tcx = self.cx.tcx(); + let param_env = tcx.param_env(self.ty_def_id); + let ty = tcx.type_of(self.ty_def_id).subst_identity(); + tcx.layout_of(param_env.and(ty)) + } + fn variant_name<'b: 'a>(&'b self, index: VariantIdx) -> Symbol { + let Adt(adt, _) = self.type_layout().unwrap().ty.kind() else { + span_bug!(self.cx.tcx().def_span(self.ty_def_id), "not an adt") + }; + adt.variant(index).name + } + fn tag_size<'b: 'a>(&'b self) -> u64 { + if let Variants::Multiple { variants, tag, tag_encoding, .. } = + self.type_layout().unwrap().layout.variants() && !variants.is_empty() { + if let TagEncoding::Niche { .. } = tag_encoding { + 0 + } else if let Primitive::Int(i, _) = tag.primitive() { + i.size().bytes() + } else { + span_bug!(self.cx.tcx().def_span(self.ty_def_id), "tag is neither niche nor int") + } + } else { + 0 + } + } + fn write_size<'b: 'a>( + &'b self, + layout: &'b LayoutS, + tag_size: u64, + ) -> impl fmt::Display + Captures<'cx> + Captures<'b> { + display_fn(move |f| { + if layout.abi.is_unsized() { + write!(f, "(unsized)")?; + } else { + let size = layout.size.bytes() - tag_size; + write!(f, "{size} byte{pl}", pl = if size == 1 { "" } else { "s" })?; + if layout.abi.is_uninhabited() { + write!( + f, + " (uninhabited)" )?; - - let Adt(adt, _) = ty_layout.ty.kind() 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.primitive() { - 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 name = adt.variant(index).name; - write!(&mut f, "
  • {name}: ")?; - write_size_of_layout(&mut f, layout, tag_size); - writeln!(&mut f, "
  • ")?; - } - f.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`. - Err(LayoutError::Unknown(_)) => { - writeln!( - f, - "

Note: Unable to compute type layout, \ - possibly due to this type having generic parameters. \ - Layout can only be computed for concrete, fully-instantiated types.

" - )?; - } - // 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. - Err(LayoutError::SizeOverflow(_)) => { - writeln!( - f, - "

Note: Encountered an error during type layout; \ - the type was too big.

" - )?; - } - Err(LayoutError::NormalizationFailure(_, _)) => { - writeln!( - f, - "

Note: Encountered an error during type layout; \ - the type failed to be normalized.

" - )?; - } + Ok(()) + }) + } + } + + display_fn(move |f| { + if !cx.shared.show_type_layout { + return Ok(()); } - writeln!(f, "
") + Ok(TypeLayout { cx, ty_def_id }.render_into(f).unwrap()) }) } diff --git a/src/librustdoc/html/templates/type_layout.html b/src/librustdoc/html/templates/type_layout.html new file mode 100644 index 0000000000000..70149d4e1ab85 --- /dev/null +++ b/src/librustdoc/html/templates/type_layout.html @@ -0,0 +1,45 @@ +

{# #} + Layout§ {# #} +

{# #} +
{# #} + {% match self.type_layout() %} + {% when Ok(ty_layout) %} +
{# #} +

{# #} + Note: Most layout information is completely {#+ #} + unstable and may even differ between compilations. {#+ #} + The only exception is types with certain repr(...) {#+ #} + attributes. Please see the Rust Reference’s {#+ #} + “Type Layout” {#+ #} + chapter for details on type layout guarantees. {# #} +

{# #} +
{# #} +

Size: {{ self.write_size(ty_layout.layout.0.borrow(), 0) | safe }}

{# #} + {% if let Some(variants) = self.variants() %} +

Size for each variant:

{# #} +
    {# #} + {% for (index, layout) in variants.iter_enumerated() %} +
  • {# #} + {{ self.variant_name(index.clone()) }}: {#+ #} + {{ self.write_size(layout, self.tag_size()) | safe }} +
  • {# #} + {% endfor %} +
{# #} + {% 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`. #} + {% when Err(LayoutError::Unknown(_)) %} +

Note: Unable to compute type layout, {#+ #} + possibly due to this type having generic parameters. {#+ #} + Layout can only be computed for concrete, fully-instantiated types.

{# #} + {# 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(_)) %} +

Note: Encountered an error during type layout; {#+ #} + the type was too big.

{# #} + {% when Err(LayoutError::NormalizationFailure(_, _)) %} +

Note: Encountered an error during type layout; {#+ #} + the type failed to be normalized.

{# #} + {% endmatch %} +
{# #} From 5f9746b94766e1dca4c4ee39da46a03a41d3fcd8 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 18 Apr 2023 10:21:04 -0700 Subject: [PATCH 2/7] rustdoc: use a separate template for type layout size --- src/librustdoc/html/render/print_item.rs | 24 +++++++++---------- .../html/templates/type_layout_size.html | 12 ++++++++++ 2 files changed, 24 insertions(+), 12 deletions(-) create mode 100644 src/librustdoc/html/templates/type_layout_size.html diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index e089b55b9c4d1..3045e4b118bfb 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1945,6 +1945,14 @@ fn document_type_layout<'a, 'cx: 'a>( ty_def_id: DefId, } + #[derive(Template)] + #[template(path = "type_layout_size.html")] + struct TypeLayoutSize { + is_unsized: bool, + is_uninhabited: bool, + size: u64, + } + impl<'a, 'cx: 'a> TypeLayout<'a, 'cx> { fn variants<'b: 'a>(&'b self) -> Option<&'b IndexVec> { if let Variants::Multiple { variants, .. } = @@ -1986,18 +1994,10 @@ fn document_type_layout<'a, 'cx: 'a>( tag_size: u64, ) -> impl fmt::Display + Captures<'cx> + Captures<'b> { display_fn(move |f| { - if layout.abi.is_unsized() { - write!(f, "(unsized)")?; - } else { - let size = layout.size.bytes() - tag_size; - write!(f, "{size} byte{pl}", pl = if size == 1 { "" } else { "s" })?; - if layout.abi.is_uninhabited() { - write!( - f, - " (uninhabited)" - )?; - } - } + let is_unsized = layout.abi.is_unsized(); + let is_uninhabited = layout.abi.is_uninhabited(); + let size = layout.size.bytes() - tag_size; + TypeLayoutSize { is_unsized, is_uninhabited, size }.render_into(f).unwrap(); Ok(()) }) } diff --git a/src/librustdoc/html/templates/type_layout_size.html b/src/librustdoc/html/templates/type_layout_size.html new file mode 100644 index 0000000000000..9c2b39edc9f37 --- /dev/null +++ b/src/librustdoc/html/templates/type_layout_size.html @@ -0,0 +1,12 @@ +{% if is_unsized %} + (unsized) +{% else %} + {% if size == 1 %} + 1 byte + {% else %} + {{ size +}} bytes + {% endif %} + {% if is_uninhabited %} + {# +#} (uninhabited) + {% endif %} +{% endif %} From 3a16db1bb4c863b2afe5ecd745c1d7a7741a5e11 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 18 Apr 2023 10:49:18 -0700 Subject: [PATCH 3/7] rustdoc: create variants list outside of template --- src/librustdoc/html/render/print_item.rs | 109 +++++++++--------- .../html/templates/type_layout.html | 14 +-- 2 files changed, 60 insertions(+), 63 deletions(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 3045e4b118bfb..3ccc694fd2a75 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -5,15 +5,13 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir as hir; use rustc_hir::def::CtorKind; use rustc_hir::def_id::DefId; -use rustc_index::vec::IndexVec; use rustc_middle::middle::stability; use rustc_middle::span_bug; -use rustc_middle::ty::layout::{LayoutError, TyAndLayout}; +use rustc_middle::ty::layout::LayoutError; use rustc_middle::ty::{self, Adt, TyCtxt}; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Symbol}; -use rustc_target::abi::{LayoutS, Primitive, TagEncoding, VariantIdx, Variants}; -use std::borrow::Borrow; +use rustc_target::abi::{Primitive, TagEncoding, Variants}; use std::cmp::Ordering; use std::fmt; use std::rc::Rc; @@ -1940,9 +1938,9 @@ fn document_type_layout<'a, 'cx: 'a>( ) -> impl fmt::Display + 'a + Captures<'cx> { #[derive(Template)] #[template(path = "type_layout.html")] - struct TypeLayout<'a, 'cx> { - cx: &'a Context<'cx>, - ty_def_id: DefId, + struct TypeLayout<'cx> { + variants: Vec<(Symbol, TypeLayoutSize)>, + type_layout_size: Result>, } #[derive(Template)] @@ -1953,62 +1951,61 @@ fn document_type_layout<'a, 'cx: 'a>( size: u64, } - impl<'a, 'cx: 'a> TypeLayout<'a, 'cx> { - fn variants<'b: 'a>(&'b self) -> Option<&'b IndexVec> { - if let Variants::Multiple { variants, .. } = - self.type_layout().unwrap().layout.variants() && !variants.is_empty() { - Some(&variants) - } else { - None - } - } - fn type_layout<'b: 'a>(&'b self) -> Result, LayoutError<'cx>> { - let tcx = self.cx.tcx(); - let param_env = tcx.param_env(self.ty_def_id); - let ty = tcx.type_of(self.ty_def_id).subst_identity(); - tcx.layout_of(param_env.and(ty)) + display_fn(move |f| { + if !cx.shared.show_type_layout { + return Ok(()); } - fn variant_name<'b: 'a>(&'b self, index: VariantIdx) -> Symbol { - let Adt(adt, _) = self.type_layout().unwrap().ty.kind() else { - span_bug!(self.cx.tcx().def_span(self.ty_def_id), "not an adt") - }; - adt.variant(index).name - } - fn tag_size<'b: 'a>(&'b self) -> u64 { - if let Variants::Multiple { variants, tag, tag_encoding, .. } = - self.type_layout().unwrap().layout.variants() && !variants.is_empty() { - if let TagEncoding::Niche { .. } = tag_encoding { - 0 - } else if let Primitive::Int(i, _) = tag.primitive() { - i.size().bytes() - } else { - span_bug!(self.cx.tcx().def_span(self.ty_def_id), "tag is neither niche nor int") - } + + let variants = { + 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)); + 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") + }; + let variants = 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(); + variants } else { - 0 + Vec::new() } - } - fn write_size<'b: 'a>( - &'b self, - layout: &'b LayoutS, - tag_size: u64, - ) -> impl fmt::Display + Captures<'cx> + Captures<'b> { - display_fn(move |f| { + }; + + let type_layout_size = { + let tcx = cx.tcx(); + let param_env = tcx.param_env(ty_def_id); + let ty = tcx.type_of(ty_def_id).subst_identity(); + 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() - tag_size; - TypeLayoutSize { is_unsized, is_uninhabited, size }.render_into(f).unwrap(); - Ok(()) + let size = layout.size.bytes(); + TypeLayoutSize { is_unsized, is_uninhabited, size } }) - } - } - - display_fn(move |f| { - if !cx.shared.show_type_layout { - return Ok(()); - } + }; - Ok(TypeLayout { cx, ty_def_id }.render_into(f).unwrap()) + Ok(TypeLayout { variants, type_layout_size }.render_into(f).unwrap()) }) } diff --git a/src/librustdoc/html/templates/type_layout.html b/src/librustdoc/html/templates/type_layout.html index 70149d4e1ab85..9e2c2049e31bb 100644 --- a/src/librustdoc/html/templates/type_layout.html +++ b/src/librustdoc/html/templates/type_layout.html @@ -2,8 +2,8 @@

{# #} Layout§ {# #}

{# #}
{# #} - {% match self.type_layout() %} - {% when Ok(ty_layout) %} + {% match type_layout_size %} + {% when Ok(type_layout_size) %}
{# #}

{# #} Note: Most layout information is completely {#+ #} @@ -14,14 +14,14 @@

{# #} chapter for details on type layout guarantees. {# #}

{# #}

{# #} -

Size: {{ self.write_size(ty_layout.layout.0.borrow(), 0) | safe }}

{# #} - {% if let Some(variants) = self.variants() %} +

Size: {{ type_layout_size|safe }}

{# #} + {% if !variants.is_empty() %}

Size for each variant:

{# #}
    {# #} - {% for (index, layout) in variants.iter_enumerated() %} + {% for (name, layout_size) in variants %}
  • {# #} - {{ self.variant_name(index.clone()) }}: {#+ #} - {{ self.write_size(layout, self.tag_size()) | safe }} + {{ name }}: {#+ #} + {{ layout_size|safe }}
  • {# #} {% endfor %}
{# #} From e26ae9530b21288ea6f9ca73d8c8d895c47807c3 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 18 Apr 2023 10:52:36 -0700 Subject: [PATCH 4/7] rustdoc: format type layout template with newline after `

` --- .../html/templates/type_layout.html | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/librustdoc/html/templates/type_layout.html b/src/librustdoc/html/templates/type_layout.html index 9e2c2049e31bb..58b220c7428f4 100644 --- a/src/librustdoc/html/templates/type_layout.html +++ b/src/librustdoc/html/templates/type_layout.html @@ -16,7 +16,9 @@

{# #}

{# #}

Size: {{ type_layout_size|safe }}

{# #} {% if !variants.is_empty() %} -

Size for each variant:

{# #} +

{# #} + Size for each variant: {# #} +

{# #}
    {# #} {% for (name, layout_size) in variants %}
  • {# #} @@ -29,17 +31,23 @@

    {# #} {# 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`. #} {% when Err(LayoutError::Unknown(_)) %} -

    Note: Unable to compute type layout, {#+ #} - possibly due to this type having generic parameters. {#+ #} - Layout can only be computed for concrete, fully-instantiated types.

    {# #} +

    {# #} + Note: Unable to compute type layout, {#+ #} + possibly due to this type having generic parameters. {#+ #} + Layout can only be computed for concrete, fully-instantiated types. {# #} +

    {# #} {# 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(_)) %} -

    Note: Encountered an error during type layout; {#+ #} - the type was too big.

    {# #} +

    {# #} + Note: Encountered an error during type layout; {#+ #} + the type was too big. {# #} +

    {# #} {% when Err(LayoutError::NormalizationFailure(_, _)) %} -

    Note: Encountered an error during type layout; {#+ #} - the type failed to be normalized.

    {# #} +

    {# #} + Note: Encountered an error during type layout; {#+ #} + the type failed to be normalized. {# #} +

    {# #} {% endmatch %} {# #} From 99e1cdb46f1b26ba8b458dded654f7f6a59973bc Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 21 Apr 2023 09:00:33 -0700 Subject: [PATCH 5/7] rustdoc: get rid of redundant, nested `let` lines --- src/librustdoc/html/render/print_item.rs | 30 ++++++++++-------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 3ccc694fd2a75..fe227244588b4 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1956,11 +1956,12 @@ fn document_type_layout<'a, 'cx: 'a>( return Ok(()); } - let variants = { - 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 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() && @@ -1991,19 +1992,14 @@ fn document_type_layout<'a, 'cx: 'a>( } else { Vec::new() } - }; + ; - let type_layout_size = { - let tcx = cx.tcx(); - let param_env = tcx.param_env(ty_def_id); - let ty = tcx.type_of(ty_def_id).subst_identity(); - 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 } - }) - }; + 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()) }) From 2b728c1f85dec11fd0e64ad89c7149e119134971 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 21 Apr 2023 10:06:31 -0700 Subject: [PATCH 6/7] rustdoc: factor `document_type_layout` into its own module --- src/librustdoc/html/render/mod.rs | 1 + src/librustdoc/html/render/print_item.rs | 79 +------------------- src/librustdoc/html/render/type_layout.rs | 87 +++++++++++++++++++++++ 3 files changed, 90 insertions(+), 77 deletions(-) create mode 100644 src/librustdoc/html/render/type_layout.rs diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 1e3cd2668506f..a699d0b38a70c 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -32,6 +32,7 @@ mod context; mod print_item; mod sidebar; mod span_map; +mod type_layout; mod write_shared; pub(crate) use self::context::*; diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index fe227244588b4..b71109f15609e 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -6,16 +6,14 @@ 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::{self, Adt, TyCtxt}; +use rustc_middle::ty::{self, TyCtxt}; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Symbol}; -use rustc_target::abi::{Primitive, TagEncoding, Variants}; use std::cmp::Ordering; use std::fmt; use std::rc::Rc; +use super::type_layout::document_type_layout; use super::{ collect_paths_for_type, document, ensure_trailing_slash, get_filtered_impls_for_reference, item_ty_to_section, notable_traits_button, notable_traits_json, render_all_impls, @@ -1932,79 +1930,6 @@ fn document_non_exhaustive<'a>(item: &'a clean::Item) -> impl fmt::Display + 'a }) } -fn document_type_layout<'a, 'cx: 'a>( - cx: &'a Context<'cx>, - ty_def_id: DefId, -) -> impl fmt::Display + 'a + Captures<'cx> { - #[derive(Template)] - #[template(path = "type_layout.html")] - struct TypeLayout<'cx> { - variants: Vec<(Symbol, TypeLayoutSize)>, - type_layout_size: Result>, - } - - #[derive(Template)] - #[template(path = "type_layout_size.html")] - struct TypeLayoutSize { - is_unsized: bool, - is_uninhabited: bool, - size: u64, - } - - 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") - }; - let variants = 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(); - variants - } 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()) - }) -} - fn pluralize(count: usize) -> &'static str { if count > 1 { "s" } else { "" } } diff --git a/src/librustdoc/html/render/type_layout.rs b/src/librustdoc/html/render/type_layout.rs new file mode 100644 index 0000000000000..0befc9625db78 --- /dev/null +++ b/src/librustdoc/html/render/type_layout.rs @@ -0,0 +1,87 @@ +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>, +} + +#[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") + }; + let variants = 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(); + variants + } 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()) + }) +} From e6664c06813b25c2edd923a8a69d57ae98b6083f Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 21 Apr 2023 11:05:24 -0700 Subject: [PATCH 7/7] rustdoc: remove unnecessary binding --- src/librustdoc/html/render/type_layout.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/html/render/type_layout.rs b/src/librustdoc/html/render/type_layout.rs index 0befc9625db78..22aec623335e8 100644 --- a/src/librustdoc/html/render/type_layout.rs +++ b/src/librustdoc/html/render/type_layout.rs @@ -56,7 +56,7 @@ pub(crate) fn document_type_layout<'a, 'cx: 'a>( } else { span_bug!(cx.tcx().def_span(ty_def_id), "tag is neither niche nor int") }; - let variants = variants + variants .iter_enumerated() .map(|(variant_idx, variant_layout)| { let Adt(adt, _) = type_layout.ty.kind() else { @@ -68,12 +68,11 @@ pub(crate) fn document_type_layout<'a, 'cx: 'a>( let size = variant_layout.size.bytes() - tag_size; let type_layout_size = TypeLayoutSize { is_unsized, is_uninhabited, size }; (name, type_layout_size) - }).collect(); - variants + }) + .collect() } else { Vec::new() - } - ; + }; let type_layout_size = tcx.layout_of(param_env.and(ty)).map(|layout| { let is_unsized = layout.abi.is_unsized();