1
+ use hir:: def_id:: DefId ;
1
2
use rustc_hir as hir;
2
3
use rustc_index:: bit_set:: BitSet ;
3
4
use rustc_index:: vec:: { Idx , IndexVec } ;
@@ -6,7 +7,7 @@ use rustc_middle::ty::layout::{
6
7
IntegerExt , LayoutCx , LayoutError , LayoutOf , TyAndLayout , MAX_SIMD_LANES ,
7
8
} ;
8
9
use rustc_middle:: ty:: {
9
- self , subst:: SubstsRef , EarlyBinder , ReprOptions , Ty , TyCtxt , TypeVisitable ,
10
+ self , subst:: SubstsRef , AdtDef , EarlyBinder , ReprOptions , Ty , TyCtxt , TypeVisitable ,
10
11
} ;
11
12
use rustc_session:: { DataTypeKind , FieldInfo , SizeKind , VariantInfo } ;
12
13
use rustc_span:: symbol:: Symbol ;
@@ -815,206 +816,186 @@ fn record_layout_for_printing_outlined<'tcx>(
815
816
} ;
816
817
817
818
match * layout. ty . kind ( ) {
818
- ty:: Adt ( ref adt_def, _) => {
819
+ ty:: Adt ( adt_def, _) => {
819
820
debug ! ( "print-type-size t: `{:?}` process adt" , layout. ty) ;
820
821
let adt_kind = adt_def. adt_kind ( ) ;
821
822
let adt_packed = adt_def. repr ( ) . pack . is_some ( ) ;
822
-
823
- let build_variant_info =
824
- |n : Option < Symbol > , flds : & [ Symbol ] , layout : TyAndLayout < ' tcx > | {
825
- let mut min_size = Size :: ZERO ;
826
- let field_info: Vec < _ > = flds
827
- . iter ( )
828
- . enumerate ( )
829
- . map ( |( i, & name) | {
830
- let field_layout = layout. field ( cx, i) ;
831
- let offset = layout. fields . offset ( i) ;
832
- min_size = min_size. max ( offset + field_layout. size ) ;
833
- FieldInfo {
834
- name,
835
- offset : offset. bytes ( ) ,
836
- size : field_layout. size . bytes ( ) ,
837
- align : field_layout. align . abi . bytes ( ) ,
838
- }
839
- } )
840
- . collect ( ) ;
841
-
842
- VariantInfo {
843
- name : n,
844
- kind : if layout. is_unsized ( ) { SizeKind :: Min } else { SizeKind :: Exact } ,
845
- align : layout. align . abi . bytes ( ) ,
846
- size : if min_size. bytes ( ) == 0 {
847
- layout. size . bytes ( )
848
- } else {
849
- min_size. bytes ( )
850
- } ,
851
- fields : field_info,
852
- }
853
- } ;
854
-
855
- match layout. variants {
856
- Variants :: Single { index } => {
857
- if !adt_def. variants ( ) . is_empty ( ) && layout. fields != FieldsShape :: Primitive {
858
- debug ! (
859
- "print-type-size `{:#?}` variant {}" ,
860
- layout,
861
- adt_def. variant( index) . name
862
- ) ;
863
- let variant_def = & adt_def. variant ( index) ;
864
- let fields: Vec < _ > = variant_def. fields . iter ( ) . map ( |f| f. name ) . collect ( ) ;
865
- record (
866
- adt_kind. into ( ) ,
867
- adt_packed,
868
- None ,
869
- vec ! [ build_variant_info( Some ( variant_def. name) , & fields, layout) ] ,
870
- ) ;
871
- } else {
872
- // (This case arises for *empty* enums; so give it
873
- // zero variants.)
874
- record ( adt_kind. into ( ) , adt_packed, None , vec ! [ ] ) ;
875
- }
876
- }
877
-
878
- Variants :: Multiple { tag, ref tag_encoding, .. } => {
879
- debug ! (
880
- "print-type-size `{:#?}` adt general variants def {}" ,
881
- layout. ty,
882
- adt_def. variants( ) . len( )
883
- ) ;
884
- let variant_infos: Vec < _ > = adt_def
885
- . variants ( )
886
- . iter_enumerated ( )
887
- . map ( |( i, variant_def) | {
888
- let fields: Vec < _ > =
889
- variant_def. fields . iter ( ) . map ( |f| f. name ) . collect ( ) ;
890
- build_variant_info (
891
- Some ( variant_def. name ) ,
892
- & fields,
893
- layout. for_variant ( cx, i) ,
894
- )
895
- } )
896
- . collect ( ) ;
897
- record (
898
- adt_kind. into ( ) ,
899
- adt_packed,
900
- match tag_encoding {
901
- TagEncoding :: Direct => Some ( tag. size ( cx) ) ,
902
- _ => None ,
903
- } ,
904
- variant_infos,
905
- ) ;
906
- }
907
- }
823
+ let ( variant_infos, opt_discr_size) = variant_info_for_adt ( cx, layout, adt_def) ;
824
+ record ( adt_kind. into ( ) , adt_packed, opt_discr_size, variant_infos) ;
908
825
}
909
826
910
827
ty:: Generator ( def_id, substs, _) => {
911
828
debug ! ( "print-type-size t: `{:?}` record generator" , layout. ty) ;
912
829
// Generators always have a begin/poisoned/end state with additional suspend points
913
- match layout. variants {
914
- Variants :: Multiple { tag, ref tag_encoding, .. } => {
915
- let ( generator, state_specific_names) =
916
- cx. tcx . generator_layout_and_saved_local_names ( def_id) ;
917
- let upvar_names = cx. tcx . closure_saved_names_of_captured_variables ( def_id) ;
918
-
919
- let mut upvars_size = Size :: ZERO ;
920
- let upvar_fields: Vec < _ > = substs
921
- . as_generator ( )
922
- . upvar_tys ( )
923
- . zip ( upvar_names)
924
- . enumerate ( )
925
- . map ( |( field_idx, ( _, name) ) | {
926
- let field_layout = layout. field ( cx, field_idx) ;
927
- let offset = layout. fields . offset ( field_idx) ;
928
- upvars_size = upvars_size. max ( offset + field_layout. size ) ;
929
- FieldInfo {
930
- name : Symbol :: intern ( & name) ,
931
- offset : offset. bytes ( ) ,
932
- size : field_layout. size . bytes ( ) ,
933
- align : field_layout. align . abi . bytes ( ) ,
934
- }
935
- } )
936
- . collect ( ) ;
937
-
938
- let variant_infos: Vec < _ > = generator
939
- . variant_fields
940
- . iter_enumerated ( )
941
- . map ( |( variant_idx, variant_def) | {
942
- let variant_layout = layout. for_variant ( cx, variant_idx) ;
943
- let mut variant_size = Size :: ZERO ;
944
- let fields = variant_def
945
- . iter ( )
946
- . enumerate ( )
947
- . map ( |( field_idx, local) | {
948
- let field_layout = variant_layout. field ( cx, field_idx) ;
949
- let offset = variant_layout. fields . offset ( field_idx) ;
950
- // The struct is as large as the last field's end
951
- variant_size = variant_size. max ( offset + field_layout. size ) ;
952
- FieldInfo {
953
- name : state_specific_names
954
- . get ( * local)
955
- . copied ( )
956
- . flatten ( )
957
- . unwrap_or ( Symbol :: intern ( & format ! (
958
- ".generator_field{}" ,
959
- local. as_usize( )
960
- ) ) ) ,
961
- offset : offset. bytes ( ) ,
962
- size : field_layout. size . bytes ( ) ,
963
- align : field_layout. align . abi . bytes ( ) ,
964
- }
965
- } )
966
- . chain ( upvar_fields. iter ( ) . copied ( ) )
967
- . collect ( ) ;
968
-
969
- // If the variant has no state-specific fields, then it's the size of the upvars.
970
- if variant_size == Size :: ZERO {
971
- variant_size = upvars_size;
972
- }
973
- // We need to add the discriminant size back into min_size, since it is subtracted
974
- // later during printing.
975
- variant_size += match tag_encoding {
976
- TagEncoding :: Direct => tag. size ( cx) ,
977
- _ => Size :: ZERO ,
978
- } ;
979
-
980
- VariantInfo {
981
- name : Some ( Symbol :: intern ( & ty:: GeneratorSubsts :: variant_name (
982
- variant_idx,
983
- ) ) ) ,
984
- kind : SizeKind :: Exact ,
985
- size : variant_size. bytes ( ) ,
986
- align : variant_layout. align . abi . bytes ( ) ,
987
- fields,
988
- }
989
- } )
990
- . collect ( ) ;
991
- record (
992
- DataTypeKind :: Generator ,
993
- false ,
994
- match tag_encoding {
995
- TagEncoding :: Direct => Some ( tag. size ( cx) ) ,
996
- _ => None ,
997
- } ,
998
- variant_infos,
999
- ) ;
1000
- }
1001
- _ => {
1002
- // This should never happen, but I would rather not panic.
1003
- record ( DataTypeKind :: Generator , false , None , vec ! [ ] ) ;
1004
- return ;
1005
- }
1006
- }
830
+ let ( variant_infos, opt_discr_size) =
831
+ variant_info_for_generator ( cx, layout, def_id, substs) ;
832
+ record ( DataTypeKind :: Generator , false , opt_discr_size, variant_infos) ;
1007
833
}
1008
834
1009
835
ty:: Closure ( ..) => {
1010
836
debug ! ( "print-type-size t: `{:?}` record closure" , layout. ty) ;
1011
837
record ( DataTypeKind :: Closure , false , None , vec ! [ ] ) ;
1012
- return ;
1013
838
}
1014
839
1015
840
_ => {
1016
841
debug ! ( "print-type-size t: `{:?}` skip non-nominal" , layout. ty) ;
1017
- return ;
1018
842
}
1019
843
} ;
1020
844
}
845
+
846
+ fn variant_info_for_adt < ' tcx > (
847
+ cx : & LayoutCx < ' tcx , TyCtxt < ' tcx > > ,
848
+ layout : TyAndLayout < ' tcx > ,
849
+ adt_def : AdtDef < ' tcx > ,
850
+ ) -> ( Vec < VariantInfo > , Option < Size > ) {
851
+ let build_variant_info = |n : Option < Symbol > , flds : & [ Symbol ] , layout : TyAndLayout < ' tcx > | {
852
+ let mut min_size = Size :: ZERO ;
853
+ let field_info: Vec < _ > = flds
854
+ . iter ( )
855
+ . enumerate ( )
856
+ . map ( |( i, & name) | {
857
+ let field_layout = layout. field ( cx, i) ;
858
+ let offset = layout. fields . offset ( i) ;
859
+ min_size = min_size. max ( offset + field_layout. size ) ;
860
+ FieldInfo {
861
+ name,
862
+ offset : offset. bytes ( ) ,
863
+ size : field_layout. size . bytes ( ) ,
864
+ align : field_layout. align . abi . bytes ( ) ,
865
+ }
866
+ } )
867
+ . collect ( ) ;
868
+
869
+ VariantInfo {
870
+ name : n,
871
+ kind : if layout. is_unsized ( ) { SizeKind :: Min } else { SizeKind :: Exact } ,
872
+ align : layout. align . abi . bytes ( ) ,
873
+ size : if min_size. bytes ( ) == 0 { layout. size . bytes ( ) } else { min_size. bytes ( ) } ,
874
+ fields : field_info,
875
+ }
876
+ } ;
877
+
878
+ match layout. variants {
879
+ Variants :: Single { index } => {
880
+ if !adt_def. variants ( ) . is_empty ( ) && layout. fields != FieldsShape :: Primitive {
881
+ debug ! ( "print-type-size `{:#?}` variant {}" , layout, adt_def. variant( index) . name) ;
882
+ let variant_def = & adt_def. variant ( index) ;
883
+ let fields: Vec < _ > = variant_def. fields . iter ( ) . map ( |f| f. name ) . collect ( ) ;
884
+ ( vec ! [ build_variant_info( Some ( variant_def. name) , & fields, layout) ] , None )
885
+ } else {
886
+ ( vec ! [ ] , None )
887
+ }
888
+ }
889
+
890
+ Variants :: Multiple { tag, ref tag_encoding, .. } => {
891
+ debug ! (
892
+ "print-type-size `{:#?}` adt general variants def {}" ,
893
+ layout. ty,
894
+ adt_def. variants( ) . len( )
895
+ ) ;
896
+ let variant_infos: Vec < _ > = adt_def
897
+ . variants ( )
898
+ . iter_enumerated ( )
899
+ . map ( |( i, variant_def) | {
900
+ let fields: Vec < _ > = variant_def. fields . iter ( ) . map ( |f| f. name ) . collect ( ) ;
901
+ build_variant_info ( Some ( variant_def. name ) , & fields, layout. for_variant ( cx, i) )
902
+ } )
903
+ . collect ( ) ;
904
+
905
+ (
906
+ variant_infos,
907
+ match tag_encoding {
908
+ TagEncoding :: Direct => Some ( tag. size ( cx) ) ,
909
+ _ => None ,
910
+ } ,
911
+ )
912
+ }
913
+ }
914
+ }
915
+
916
+ fn variant_info_for_generator < ' tcx > (
917
+ cx : & LayoutCx < ' tcx , TyCtxt < ' tcx > > ,
918
+ layout : TyAndLayout < ' tcx > ,
919
+ def_id : DefId ,
920
+ substs : ty:: SubstsRef < ' tcx > ,
921
+ ) -> ( Vec < VariantInfo > , Option < Size > ) {
922
+ let Variants :: Multiple { tag, ref tag_encoding, .. } = layout. variants else {
923
+ return ( vec ! [ ] , None ) ;
924
+ } ;
925
+
926
+ let ( generator, state_specific_names) = cx. tcx . generator_layout_and_saved_local_names ( def_id) ;
927
+ let upvar_names = cx. tcx . closure_saved_names_of_captured_variables ( def_id) ;
928
+
929
+ let mut upvars_size = Size :: ZERO ;
930
+ let upvar_fields: Vec < _ > = substs
931
+ . as_generator ( )
932
+ . upvar_tys ( )
933
+ . zip ( upvar_names)
934
+ . enumerate ( )
935
+ . map ( |( field_idx, ( _, name) ) | {
936
+ let field_layout = layout. field ( cx, field_idx) ;
937
+ let offset = layout. fields . offset ( field_idx) ;
938
+ upvars_size = upvars_size. max ( offset + field_layout. size ) ;
939
+ FieldInfo {
940
+ name : Symbol :: intern ( & name) ,
941
+ offset : offset. bytes ( ) ,
942
+ size : field_layout. size . bytes ( ) ,
943
+ align : field_layout. align . abi . bytes ( ) ,
944
+ }
945
+ } )
946
+ . collect ( ) ;
947
+
948
+ let variant_infos: Vec < _ > = generator
949
+ . variant_fields
950
+ . iter_enumerated ( )
951
+ . map ( |( variant_idx, variant_def) | {
952
+ let variant_layout = layout. for_variant ( cx, variant_idx) ;
953
+ let mut variant_size = Size :: ZERO ;
954
+ let fields = variant_def
955
+ . iter ( )
956
+ . enumerate ( )
957
+ . map ( |( field_idx, local) | {
958
+ let field_layout = variant_layout. field ( cx, field_idx) ;
959
+ let offset = variant_layout. fields . offset ( field_idx) ;
960
+ // The struct is as large as the last field's end
961
+ variant_size = variant_size. max ( offset + field_layout. size ) ;
962
+ FieldInfo {
963
+ name : state_specific_names. get ( * local) . copied ( ) . flatten ( ) . unwrap_or (
964
+ Symbol :: intern ( & format ! ( ".generator_field{}" , local. as_usize( ) ) ) ,
965
+ ) ,
966
+ offset : offset. bytes ( ) ,
967
+ size : field_layout. size . bytes ( ) ,
968
+ align : field_layout. align . abi . bytes ( ) ,
969
+ }
970
+ } )
971
+ . chain ( upvar_fields. iter ( ) . copied ( ) )
972
+ . collect ( ) ;
973
+
974
+ // If the variant has no state-specific fields, then it's the size of the upvars.
975
+ if variant_size == Size :: ZERO {
976
+ variant_size = upvars_size;
977
+ }
978
+ // We need to add the discriminant size back into min_size, since it is subtracted
979
+ // later during printing.
980
+ variant_size += match tag_encoding {
981
+ TagEncoding :: Direct => tag. size ( cx) ,
982
+ _ => Size :: ZERO ,
983
+ } ;
984
+
985
+ VariantInfo {
986
+ name : Some ( Symbol :: intern ( & ty:: GeneratorSubsts :: variant_name ( variant_idx) ) ) ,
987
+ kind : SizeKind :: Exact ,
988
+ size : variant_size. bytes ( ) ,
989
+ align : variant_layout. align . abi . bytes ( ) ,
990
+ fields,
991
+ }
992
+ } )
993
+ . collect ( ) ;
994
+ (
995
+ variant_infos,
996
+ match tag_encoding {
997
+ TagEncoding :: Direct => Some ( tag. size ( cx) ) ,
998
+ _ => None ,
999
+ } ,
1000
+ )
1001
+ }
0 commit comments