@@ -11,7 +11,7 @@ use tracing::{debug, trace};
1111use crate :: {
1212 AbiAlign , Align , BackendRepr , FieldsShape , HasDataLayout , IndexSlice , IndexVec , Integer ,
1313 LayoutData , Niche , NonZeroUsize , NumScalableVectors , Primitive , ReprOptions , Scalar , Size ,
14- StructKind , TagEncoding , TargetDataLayout , Variants , WrappingRange ,
14+ StructKind , TagEncoding , TargetDataLayout , VariantLayout , Variants , WrappingRange ,
1515} ;
1616
1717mod coroutine;
@@ -638,6 +638,10 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
638638 }
639639
640640 let calculate_niche_filling_layout = || -> Option < LayoutData < FieldIdx , VariantIdx > > {
641+ struct VariantLayoutInfo {
642+ align_abi : Align ,
643+ }
644+
641645 if repr. inhibit_enum_layout_opt ( ) {
642646 return None ;
643647 }
@@ -649,26 +653,35 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
649653 let mut align = dl. aggregate_align ;
650654 let mut max_repr_align = repr. align ;
651655 let mut unadjusted_abi_align = align;
656+ let mut combined_seed = repr. field_shuffle_seed ;
657+
658+ let mut largest_variant_size = Size :: ZERO ;
659+ let mut largest_variant_index = VariantIdx :: new ( 0 ) ;
660+ let mut largest_variant_niche = None ;
652661
662+ let mut variants_info = IndexVec :: < VariantIdx , _ > :: with_capacity ( variants. len ( ) ) ;
653663 let mut variant_layouts = variants
654664 . iter_enumerated ( )
655- . map ( |( j, v) | {
656- let mut st = self . univariant ( v, repr, StructKind :: AlwaysSized ) . ok ( ) ?;
657- st. variants = Variants :: Single { index : j } ;
665+ . map ( |( i, v) | {
666+ let st = self . univariant ( v, repr, StructKind :: AlwaysSized ) . ok ( ) ?;
667+
668+ variants_info. push ( VariantLayoutInfo { align_abi : st. align . abi } ) ;
669+
670+ if st. size > largest_variant_size {
671+ largest_variant_index = i;
672+ largest_variant_size = st. size ;
673+ largest_variant_niche = st. largest_niche ;
674+ }
658675
659676 align = align. max ( st. align . abi ) ;
660677 max_repr_align = max_repr_align. max ( st. max_repr_align ) ;
661678 unadjusted_abi_align = unadjusted_abi_align. max ( st. unadjusted_abi_align ) ;
679+ combined_seed = combined_seed. wrapping_add ( st. randomization_seed ) ;
662680
663- Some ( st )
681+ Some ( VariantLayout :: from_layout ( st ) )
664682 } )
665683 . collect :: < Option < IndexVec < VariantIdx , _ > > > ( ) ?;
666684
667- let largest_variant_index = variant_layouts
668- . iter_enumerated ( )
669- . max_by_key ( |( _i, layout) | layout. size . bytes ( ) )
670- . map ( |( i, _layout) | i) ?;
671-
672685 let all_indices = variants. indices ( ) ;
673686 let needs_disc =
674687 |index : VariantIdx | index != largest_variant_index && !absent ( & variants[ index] ) ;
@@ -679,42 +692,33 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
679692 ( niche_variants. end ( ) . index ( ) as u128 - niche_variants. start ( ) . index ( ) as u128 ) + 1 ;
680693
681694 // Use the largest niche in the largest variant.
682- let niche = variant_layouts [ largest_variant_index ] . largest_niche ?;
695+ let niche = largest_variant_niche ?;
683696 let ( niche_start, niche_scalar) = niche. reserve ( dl, count) ?;
684697 let niche_offset = niche. offset ;
685698 let niche_size = niche. value . size ( dl) ;
686- let size = variant_layouts [ largest_variant_index ] . size . align_to ( align) ;
699+ let size = largest_variant_size . align_to ( align) ;
687700
688701 let all_variants_fit = variant_layouts. iter_enumerated_mut ( ) . all ( |( i, layout) | {
689702 if i == largest_variant_index {
690703 return true ;
691704 }
692705
693- layout. largest_niche = None ;
694-
695706 if layout. size <= niche_offset {
696707 // This variant will fit before the niche.
697708 return true ;
698709 }
699710
700711 // Determine if it'll fit after the niche.
701- let this_align = layout . align . abi ;
712+ let this_align = variants_info [ i ] . align_abi ;
702713 let this_offset = ( niche_offset + niche_size) . align_to ( this_align) ;
703714
704715 if this_offset + layout. size > size {
705716 return false ;
706717 }
707718
708719 // It'll fit, but we need to make some adjustments.
709- match layout. fields {
710- FieldsShape :: Arbitrary { ref mut offsets, .. } => {
711- for offset in offsets. iter_mut ( ) {
712- * offset += this_offset;
713- }
714- }
715- FieldsShape :: Primitive | FieldsShape :: Array { .. } | FieldsShape :: Union ( ..) => {
716- panic ! ( "Layout of fields should be Arbitrary for variants" )
717- }
720+ for offset in layout. field_offsets . iter_mut ( ) {
721+ * offset += this_offset;
718722 }
719723
720724 // It can't be a Scalar or ScalarPair because the offset isn't 0.
@@ -736,7 +740,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
736740 . iter_enumerated ( )
737741 . all ( |( i, layout) | i == largest_variant_index || layout. size == Size :: ZERO ) ;
738742 let same_size = size == variant_layouts[ largest_variant_index] . size ;
739- let same_align = align == variant_layouts [ largest_variant_index] . align . abi ;
743+ let same_align = align == variants_info [ largest_variant_index] . align_abi ;
740744
741745 let uninhabited = variant_layouts. iter ( ) . all ( |v| v. is_uninhabited ( ) ) ;
742746 let abi = if same_size && same_align && others_zst {
@@ -759,11 +763,6 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
759763 BackendRepr :: Memory { sized : true }
760764 } ;
761765
762- let combined_seed = variant_layouts
763- . iter ( )
764- . map ( |v| v. randomization_seed )
765- . fold ( repr. field_shuffle_seed , |acc, seed| acc. wrapping_add ( seed) ) ;
766-
767766 let layout = LayoutData {
768767 variants : Variants :: Multiple {
769768 tag : niche_scalar,
@@ -856,6 +855,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
856855 let mut align = dl. aggregate_align ;
857856 let mut max_repr_align = repr. align ;
858857 let mut unadjusted_abi_align = align;
858+ let mut combined_seed = repr. field_shuffle_seed ;
859859
860860 let mut size = Size :: ZERO ;
861861
@@ -879,14 +879,13 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
879879
880880 // Create the set of structs that represent each variant.
881881 let mut layout_variants = variants
882- . iter_enumerated ( )
883- . map ( |( i , field_layouts) | {
884- let mut st = self . univariant (
882+ . iter ( )
883+ . map ( |field_layouts| {
884+ let st = self . univariant (
885885 field_layouts,
886886 repr,
887887 StructKind :: Prefixed ( min_ity. size ( ) , prefix_align) ,
888888 ) ?;
889- st. variants = Variants :: Single { index : i } ;
890889 // Find the first field we can't move later
891890 // to make room for a larger discriminant.
892891 for field_idx in st. fields . index_by_increasing_offset ( ) {
@@ -900,7 +899,8 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
900899 align = align. max ( st. align . abi ) ;
901900 max_repr_align = max_repr_align. max ( st. max_repr_align ) ;
902901 unadjusted_abi_align = unadjusted_abi_align. max ( st. unadjusted_abi_align ) ;
903- Ok ( st)
902+ combined_seed = combined_seed. wrapping_add ( st. randomization_seed ) ;
903+ Ok ( VariantLayout :: from_layout ( st) )
904904 } )
905905 . collect :: < Result < IndexVec < VariantIdx , _ > , _ > > ( ) ?;
906906
@@ -955,23 +955,16 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
955955 let old_ity_size = min_ity. size ( ) ;
956956 let new_ity_size = ity. size ( ) ;
957957 for variant in & mut layout_variants {
958- match variant. fields {
959- FieldsShape :: Arbitrary { ref mut offsets, .. } => {
960- for i in offsets {
961- if * i <= old_ity_size {
962- assert_eq ! ( * i, old_ity_size) ;
963- * i = new_ity_size;
964- }
965- }
966- // We might be making the struct larger.
967- if variant. size <= old_ity_size {
968- variant. size = new_ity_size;
969- }
970- }
971- FieldsShape :: Primitive | FieldsShape :: Array { .. } | FieldsShape :: Union ( ..) => {
972- panic ! ( "encountered a non-arbitrary layout during enum layout" )
958+ for i in & mut variant. field_offsets {
959+ if * i <= old_ity_size {
960+ assert_eq ! ( * i, old_ity_size) ;
961+ * i = new_ity_size;
973962 }
974963 }
964+ // We might be making the struct larger.
965+ if variant. size <= old_ity_size {
966+ variant. size = new_ity_size;
967+ }
975968 }
976969 }
977970
@@ -996,12 +989,10 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
996989 let mut common_prim = None ;
997990 let mut common_prim_initialized_in_all_variants = true ;
998991 for ( field_layouts, layout_variant) in iter:: zip ( variants, & layout_variants) {
999- let FieldsShape :: Arbitrary { ref offsets, .. } = layout_variant. fields else {
1000- panic ! ( "encountered a non-arbitrary layout during enum layout" ) ;
1001- } ;
1002992 // We skip *all* ZST here and later check if we are good in terms of alignment.
1003993 // This lets us handle some cases involving aligned ZST.
1004- let mut fields = iter:: zip ( field_layouts, offsets) . filter ( |p| !p. 0 . is_zst ( ) ) ;
994+ let mut fields = iter:: zip ( field_layouts, & layout_variant. field_offsets )
995+ . filter ( |p| !p. 0 . is_zst ( ) ) ;
1005996 let ( field, offset) = match ( fields. next ( ) , fields. next ( ) ) {
1006997 ( None , None ) => {
1007998 common_prim_initialized_in_all_variants = false ;
@@ -1096,25 +1087,17 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
10961087 for variant in & mut layout_variants {
10971088 // We only do this for variants with fields; the others are not accessed anyway.
10981089 // Also do not overwrite any already existing "clever" ABIs.
1099- if variant. fields . count ( ) > 0
1100- && matches ! ( variant. backend_repr, BackendRepr :: Memory { .. } )
1090+ if matches ! ( variant. backend_repr, BackendRepr :: Memory { .. } if variant. has_fields( ) )
11011091 {
11021092 variant. backend_repr = abi;
1103- // Also need to bump up the size and alignment, so that the entire value fits
1104- // in here.
1093+ // Also need to bump up the size, so that the entire value fits in here.
11051094 variant. size = cmp:: max ( variant. size , size) ;
1106- variant. align . abi = cmp:: max ( variant. align . abi , align) ;
11071095 }
11081096 }
11091097 }
11101098
11111099 let largest_niche = Niche :: from_scalar ( dl, Size :: ZERO , tag) ;
11121100
1113- let combined_seed = layout_variants
1114- . iter ( )
1115- . map ( |v| v. randomization_seed )
1116- . fold ( repr. field_shuffle_seed , |acc, seed| acc. wrapping_add ( seed) ) ;
1117-
11181101 let tagged_layout = LayoutData {
11191102 variants : Variants :: Multiple {
11201103 tag,
0 commit comments