@@ -814,10 +814,196 @@ fn record_layout_for_printing_outlined<'tcx>(
814
814
) ;
815
815
} ;
816
816
817
- let adt_def = match * layout. ty . kind ( ) {
817
+ match * layout. ty . kind ( ) {
818
818
ty:: Adt ( ref adt_def, _) => {
819
819
debug ! ( "print-type-size t: `{:?}` process adt" , layout. ty) ;
820
- adt_def
820
+ let adt_kind = adt_def. adt_kind ( ) ;
821
+ 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
+ }
908
+ }
909
+
910
+ ty:: Generator ( def_id, substs, _) => {
911
+ debug ! ( "print-type-size t: `{:?}` record generator" , layout. ty) ;
912
+ // 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
+ }
821
1007
}
822
1008
823
1009
ty:: Closure ( ..) => {
@@ -826,93 +1012,9 @@ fn record_layout_for_printing_outlined<'tcx>(
826
1012
return ;
827
1013
}
828
1014
829
- ty:: Generator ( ..) => {
830
- debug ! ( "print-type-size t: `{:?}` record generator" , layout. ty) ;
831
- record ( DataTypeKind :: Generator , false , None , vec ! [ ] ) ;
832
- return ;
833
- }
834
-
835
1015
_ => {
836
1016
debug ! ( "print-type-size t: `{:?}` skip non-nominal" , layout. ty) ;
837
1017
return ;
838
1018
}
839
1019
} ;
840
-
841
- let adt_kind = adt_def. adt_kind ( ) ;
842
- let adt_packed = adt_def. repr ( ) . pack . is_some ( ) ;
843
-
844
- let build_variant_info = |n : Option < Symbol > , flds : & [ Symbol ] , layout : TyAndLayout < ' tcx > | {
845
- let mut min_size = Size :: ZERO ;
846
- let field_info: Vec < _ > = flds
847
- . iter ( )
848
- . enumerate ( )
849
- . map ( |( i, & name) | {
850
- let field_layout = layout. field ( cx, i) ;
851
- let offset = layout. fields . offset ( i) ;
852
- let field_end = offset + field_layout. size ;
853
- if min_size < field_end {
854
- min_size = field_end;
855
- }
856
- FieldInfo {
857
- name,
858
- offset : offset. bytes ( ) ,
859
- size : field_layout. size . bytes ( ) ,
860
- align : field_layout. align . abi . bytes ( ) ,
861
- }
862
- } )
863
- . collect ( ) ;
864
-
865
- VariantInfo {
866
- name : n,
867
- kind : if layout. is_unsized ( ) { SizeKind :: Min } else { SizeKind :: Exact } ,
868
- align : layout. align . abi . bytes ( ) ,
869
- size : if min_size. bytes ( ) == 0 { layout. size . bytes ( ) } else { min_size. bytes ( ) } ,
870
- fields : field_info,
871
- }
872
- } ;
873
-
874
- match layout. variants {
875
- Variants :: Single { index } => {
876
- if !adt_def. variants ( ) . is_empty ( ) && layout. fields != FieldsShape :: Primitive {
877
- debug ! ( "print-type-size `{:#?}` variant {}" , layout, adt_def. variant( index) . name) ;
878
- let variant_def = & adt_def. variant ( index) ;
879
- let fields: Vec < _ > = variant_def. fields . iter ( ) . map ( |f| f. name ) . collect ( ) ;
880
- record (
881
- adt_kind. into ( ) ,
882
- adt_packed,
883
- None ,
884
- vec ! [ build_variant_info( Some ( variant_def. name) , & fields, layout) ] ,
885
- ) ;
886
- } else {
887
- // (This case arises for *empty* enums; so give it
888
- // zero variants.)
889
- record ( adt_kind. into ( ) , adt_packed, None , vec ! [ ] ) ;
890
- }
891
- }
892
-
893
- Variants :: Multiple { tag, ref tag_encoding, .. } => {
894
- debug ! (
895
- "print-type-size `{:#?}` adt general variants def {}" ,
896
- layout. ty,
897
- adt_def. variants( ) . len( )
898
- ) ;
899
- let variant_infos: Vec < _ > = adt_def
900
- . variants ( )
901
- . iter_enumerated ( )
902
- . map ( |( i, variant_def) | {
903
- let fields: Vec < _ > = variant_def. fields . iter ( ) . map ( |f| f. name ) . collect ( ) ;
904
- build_variant_info ( Some ( variant_def. name ) , & fields, layout. for_variant ( cx, i) )
905
- } )
906
- . collect ( ) ;
907
- record (
908
- adt_kind. into ( ) ,
909
- adt_packed,
910
- match tag_encoding {
911
- TagEncoding :: Direct => Some ( tag. size ( cx) ) ,
912
- _ => None ,
913
- } ,
914
- variant_infos,
915
- ) ;
916
- }
917
- }
918
1020
}
0 commit comments