@@ -814,10 +814,196 @@ fn record_layout_for_printing_outlined<'tcx>(
814814 ) ;
815815 } ;
816816
817- let adt_def = match * layout. ty . kind ( ) {
817+ match * layout. ty . kind ( ) {
818818 ty:: Adt ( ref adt_def, _) => {
819819 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+ }
8211007 }
8221008
8231009 ty:: Closure ( ..) => {
@@ -826,93 +1012,9 @@ fn record_layout_for_printing_outlined<'tcx>(
8261012 return ;
8271013 }
8281014
829- ty:: Generator ( ..) => {
830- debug ! ( "print-type-size t: `{:?}` record generator" , layout. ty) ;
831- record ( DataTypeKind :: Generator , false , None , vec ! [ ] ) ;
832- return ;
833- }
834-
8351015 _ => {
8361016 debug ! ( "print-type-size t: `{:?}` skip non-nominal" , layout. ty) ;
8371017 return ;
8381018 }
8391019 } ;
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- }
9181020}
0 commit comments