@@ -5,13 +5,15 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
5
5
use rustc_hir as hir;
6
6
use rustc_hir:: def:: CtorKind ;
7
7
use rustc_hir:: def_id:: DefId ;
8
+ use rustc_index:: vec:: IndexVec ;
8
9
use rustc_middle:: middle:: stability;
9
10
use rustc_middle:: span_bug;
10
- use rustc_middle:: ty:: layout:: LayoutError ;
11
+ use rustc_middle:: ty:: layout:: { LayoutError , TyAndLayout } ;
11
12
use rustc_middle:: ty:: { self , Adt , TyCtxt } ;
12
13
use rustc_span:: hygiene:: MacroKind ;
13
14
use rustc_span:: symbol:: { kw, sym, Symbol } ;
14
- use rustc_target:: abi:: { LayoutS , Primitive , TagEncoding , Variants } ;
15
+ use rustc_target:: abi:: { LayoutS , Primitive , TagEncoding , VariantIdx , Variants } ;
16
+ use std:: borrow:: Borrow ;
15
17
use std:: cmp:: Ordering ;
16
18
use std:: fmt;
17
19
use std:: rc:: Rc ;
@@ -1936,111 +1938,77 @@ fn document_type_layout<'a, 'cx: 'a>(
1936
1938
cx : & ' a Context < ' cx > ,
1937
1939
ty_def_id : DefId ,
1938
1940
) -> impl fmt:: Display + ' a + Captures < ' cx > {
1939
- fn write_size_of_layout ( mut w : impl fmt:: Write , layout : & LayoutS , tag_size : u64 ) {
1940
- if layout. abi . is_unsized ( ) {
1941
- write ! ( w, "(unsized)" ) . unwrap ( ) ;
1942
- } else {
1943
- let size = layout. size . bytes ( ) - tag_size;
1944
- write ! ( w, "{size} byte{pl}" , pl = if size == 1 { "" } else { "s" } ) . unwrap ( ) ;
1945
- if layout. abi . is_uninhabited ( ) {
1946
- write ! (
1947
- w,
1948
- " (<a href=\" https://doc.rust-lang.org/stable/reference/glossary.html#uninhabited\" >uninhabited</a>)"
1949
- ) . unwrap ( ) ;
1950
- }
1951
- }
1941
+ #[ derive( Template ) ]
1942
+ #[ template( path = "type_layout.html" ) ]
1943
+ struct TypeLayout < ' a , ' cx > {
1944
+ cx : & ' a Context < ' cx > ,
1945
+ ty_def_id : DefId ,
1952
1946
}
1953
1947
1954
- display_fn ( move |mut f| {
1955
- if !cx. shared . show_type_layout {
1956
- return Ok ( ( ) ) ;
1948
+ impl < ' a , ' cx : ' a > TypeLayout < ' a , ' cx > {
1949
+ fn variants < ' b : ' a > ( & ' b self ) -> Option < & ' b IndexVec < VariantIdx , LayoutS > > {
1950
+ if let Variants :: Multiple { variants, .. } =
1951
+ self . type_layout ( ) . unwrap ( ) . layout . variants ( ) && !variants. is_empty ( ) {
1952
+ Some ( & variants)
1953
+ } else {
1954
+ None
1955
+ }
1957
1956
}
1958
-
1959
- writeln ! (
1960
- f,
1961
- "<h2 id=\" layout\" class=\" small-section-header\" > \
1962
- Layout<a href=\" #layout\" class=\" anchor\" >§</a></h2>"
1963
- ) ?;
1964
- writeln ! ( f, "<div class=\" docblock\" >" ) ?;
1965
-
1966
- let tcx = cx. tcx ( ) ;
1967
- let param_env = tcx. param_env ( ty_def_id) ;
1968
- let ty = tcx. type_of ( ty_def_id) . subst_identity ( ) ;
1969
- match tcx. layout_of ( param_env. and ( ty) ) {
1970
- Ok ( ty_layout) => {
1971
- writeln ! (
1972
- f,
1973
- "<div class=\" warning\" ><p><strong>Note:</strong> Most layout information is \
1974
- <strong>completely unstable</strong> and may even differ between compilations. \
1975
- The only exception is types with certain <code>repr(...)</code> attributes. \
1976
- Please see the Rust Reference’s \
1977
- <a href=\" https://doc.rust-lang.org/reference/type-layout.html\" >“Type Layout”</a> \
1978
- chapter for details on type layout guarantees.</p></div>"
1979
- ) ?;
1980
- f. write_str ( "<p><strong>Size:</strong> " ) ?;
1981
- write_size_of_layout ( & mut f, & ty_layout. layout . 0 , 0 ) ;
1982
- writeln ! ( f, "</p>" ) ?;
1983
- if let Variants :: Multiple { variants, tag, tag_encoding, .. } =
1984
- & ty_layout. layout . variants ( )
1985
- {
1986
- if !variants. is_empty ( ) {
1987
- f. write_str (
1988
- "<p><strong>Size for each variant:</strong></p>\
1989
- <ul>",
1957
+ fn type_layout < ' b : ' a > ( & ' b self ) -> Result < TyAndLayout < ' cx > , LayoutError < ' cx > > {
1958
+ let tcx = self . cx . tcx ( ) ;
1959
+ let param_env = tcx. param_env ( self . ty_def_id ) ;
1960
+ let ty = tcx. type_of ( self . ty_def_id ) . subst_identity ( ) ;
1961
+ tcx. layout_of ( param_env. and ( ty) )
1962
+ }
1963
+ fn variant_name < ' b : ' a > ( & ' b self , index : VariantIdx ) -> Symbol {
1964
+ let Adt ( adt, _) = self . type_layout ( ) . unwrap ( ) . ty . kind ( ) else {
1965
+ span_bug ! ( self . cx. tcx( ) . def_span( self . ty_def_id) , "not an adt" )
1966
+ } ;
1967
+ adt. variant ( index) . name
1968
+ }
1969
+ fn tag_size < ' b : ' a > ( & ' b self ) -> u64 {
1970
+ if let Variants :: Multiple { variants, tag, tag_encoding, .. } =
1971
+ self . type_layout ( ) . unwrap ( ) . layout . variants ( ) && !variants. is_empty ( ) {
1972
+ if let TagEncoding :: Niche { .. } = tag_encoding {
1973
+ 0
1974
+ } else if let Primitive :: Int ( i, _) = tag. primitive ( ) {
1975
+ i. size ( ) . bytes ( )
1976
+ } else {
1977
+ span_bug ! ( self . cx. tcx( ) . def_span( self . ty_def_id) , "tag is neither niche nor int" )
1978
+ }
1979
+ } else {
1980
+ 0
1981
+ }
1982
+ }
1983
+ fn write_size < ' b : ' a > (
1984
+ & ' b self ,
1985
+ layout : & ' b LayoutS ,
1986
+ tag_size : u64 ,
1987
+ ) -> impl fmt:: Display + Captures < ' cx > + Captures < ' b > {
1988
+ display_fn ( move |f| {
1989
+ if layout. abi . is_unsized ( ) {
1990
+ write ! ( f, "(unsized)" ) ?;
1991
+ } else {
1992
+ let size = layout. size . bytes ( ) - tag_size;
1993
+ write ! ( f, "{size} byte{pl}" , pl = if size == 1 { "" } else { "s" } ) ?;
1994
+ if layout. abi . is_uninhabited ( ) {
1995
+ write ! (
1996
+ f,
1997
+ " (<a href=\" https://doc.rust-lang.org/stable/reference/glossary.html#uninhabited\" >uninhabited</a>)"
1990
1998
) ?;
1991
-
1992
- let Adt ( adt, _) = ty_layout. ty . kind ( ) else {
1993
- span_bug ! ( tcx. def_span( ty_def_id) , "not an adt" )
1994
- } ;
1995
-
1996
- let tag_size = if let TagEncoding :: Niche { .. } = tag_encoding {
1997
- 0
1998
- } else if let Primitive :: Int ( i, _) = tag. primitive ( ) {
1999
- i. size ( ) . bytes ( )
2000
- } else {
2001
- span_bug ! ( tcx. def_span( ty_def_id) , "tag is neither niche nor int" )
2002
- } ;
2003
-
2004
- for ( index, layout) in variants. iter_enumerated ( ) {
2005
- let name = adt. variant ( index) . name ;
2006
- write ! ( & mut f, "<li><code>{name}</code>: " ) ?;
2007
- write_size_of_layout ( & mut f, layout, tag_size) ;
2008
- writeln ! ( & mut f, "</li>" ) ?;
2009
- }
2010
- f. write_str ( "</ul>" ) ?;
2011
1999
}
2012
2000
}
2013
- }
2014
- // This kind of layout error can occur with valid code, e.g. if you try to
2015
- // get the layout of a generic type such as `Vec<T>`.
2016
- Err ( LayoutError :: Unknown ( _) ) => {
2017
- writeln ! (
2018
- f,
2019
- "<p><strong>Note:</strong> Unable to compute type layout, \
2020
- possibly due to this type having generic parameters. \
2021
- Layout can only be computed for concrete, fully-instantiated types.</p>"
2022
- ) ?;
2023
- }
2024
- // This kind of error probably can't happen with valid code, but we don't
2025
- // want to panic and prevent the docs from building, so we just let the
2026
- // user know that we couldn't compute the layout.
2027
- Err ( LayoutError :: SizeOverflow ( _) ) => {
2028
- writeln ! (
2029
- f,
2030
- "<p><strong>Note:</strong> Encountered an error during type layout; \
2031
- the type was too big.</p>"
2032
- ) ?;
2033
- }
2034
- Err ( LayoutError :: NormalizationFailure ( _, _) ) => {
2035
- writeln ! (
2036
- f,
2037
- "<p><strong>Note:</strong> Encountered an error during type layout; \
2038
- the type failed to be normalized.</p>"
2039
- ) ?;
2040
- }
2001
+ Ok ( ( ) )
2002
+ } )
2003
+ }
2004
+ }
2005
+
2006
+ display_fn ( move |f| {
2007
+ if !cx. shared . show_type_layout {
2008
+ return Ok ( ( ) ) ;
2041
2009
}
2042
2010
2043
- writeln ! ( f , "</div>" )
2011
+ Ok ( TypeLayout { cx , ty_def_id } . render_into ( f ) . unwrap ( ) )
2044
2012
} )
2045
2013
}
2046
2014
0 commit comments