1+ use hir:: def_id:: DefId ;
12use rustc_hir as hir;
23use rustc_index:: bit_set:: BitSet ;
34use rustc_index:: vec:: { Idx , IndexVec } ;
@@ -6,7 +7,7 @@ use rustc_middle::ty::layout::{
67 IntegerExt , LayoutCx , LayoutError , LayoutOf , TyAndLayout , MAX_SIMD_LANES ,
78} ;
89use rustc_middle:: ty:: {
9- self , subst:: SubstsRef , EarlyBinder , ReprOptions , Ty , TyCtxt , TypeVisitable ,
10+ self , subst:: SubstsRef , AdtDef , EarlyBinder , ReprOptions , Ty , TyCtxt , TypeVisitable ,
1011} ;
1112use rustc_session:: { DataTypeKind , FieldInfo , SizeKind , VariantInfo } ;
1213use rustc_span:: symbol:: Symbol ;
@@ -815,206 +816,186 @@ fn record_layout_for_printing_outlined<'tcx>(
815816 } ;
816817
817818 match * layout. ty . kind ( ) {
818- ty:: Adt ( ref adt_def, _) => {
819+ ty:: Adt ( adt_def, _) => {
819820 debug ! ( "print-type-size t: `{:?}` process adt" , layout. ty) ;
820821 let adt_kind = adt_def. adt_kind ( ) ;
821822 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) ;
908825 }
909826
910827 ty:: Generator ( def_id, substs, _) => {
911828 debug ! ( "print-type-size t: `{:?}` record generator" , layout. ty) ;
912829 // 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) ;
1007833 }
1008834
1009835 ty:: Closure ( ..) => {
1010836 debug ! ( "print-type-size t: `{:?}` record closure" , layout. ty) ;
1011837 record ( DataTypeKind :: Closure , false , None , vec ! [ ] ) ;
1012- return ;
1013838 }
1014839
1015840 _ => {
1016841 debug ! ( "print-type-size t: `{:?}` skip non-nominal" , layout. ty) ;
1017- return ;
1018842 }
1019843 } ;
1020844}
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