@@ -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,18 +653,22 @@ 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 ;
652657
658+ let mut variants_info = IndexVec :: < VariantIdx , _ > :: with_capacity ( variants. len ( ) ) ;
653659 let mut variant_layouts = variants
654- . iter_enumerated ( )
655- . map ( |( j, v) | {
656- let mut st = self . univariant ( v, repr, StructKind :: AlwaysSized ) . ok ( ) ?;
657- st. variants = Variants :: Single { index : j } ;
660+ . iter ( )
661+ . map ( |v| {
662+ let st = self . univariant ( v, repr, StructKind :: AlwaysSized ) . ok ( ) ?;
663+
664+ variants_info. push ( VariantLayoutInfo { align_abi : st. align . abi } ) ;
658665
659666 align = align. max ( st. align . abi ) ;
660667 max_repr_align = max_repr_align. max ( st. max_repr_align ) ;
661668 unadjusted_abi_align = unadjusted_abi_align. max ( st. unadjusted_abi_align ) ;
669+ combined_seed = combined_seed. wrapping_add ( st. randomization_seed ) ;
662670
663- Some ( st )
671+ Some ( VariantLayout :: from_layout ( st ) )
664672 } )
665673 . collect :: < Option < IndexVec < VariantIdx , _ > > > ( ) ?;
666674
@@ -698,23 +706,16 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
698706 }
699707
700708 // Determine if it'll fit after the niche.
701- let this_align = layout . align . abi ;
709+ let this_align = variants_info [ i ] . align_abi ;
702710 let this_offset = ( niche_offset + niche_size) . align_to ( this_align) ;
703711
704712 if this_offset + layout. size > size {
705713 return false ;
706714 }
707715
708716 // 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- }
717+ for offset in layout. field_offsets . iter_mut ( ) {
718+ * offset += this_offset;
718719 }
719720
720721 // It can't be a Scalar or ScalarPair because the offset isn't 0.
@@ -736,7 +737,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
736737 . iter_enumerated ( )
737738 . all ( |( i, layout) | i == largest_variant_index || layout. size == Size :: ZERO ) ;
738739 let same_size = size == variant_layouts[ largest_variant_index] . size ;
739- let same_align = align == variant_layouts [ largest_variant_index] . align . abi ;
740+ let same_align = align == variants_info [ largest_variant_index] . align_abi ;
740741
741742 let uninhabited = variant_layouts. iter ( ) . all ( |v| v. is_uninhabited ( ) ) ;
742743 let abi = if same_size && same_align && others_zst {
@@ -759,11 +760,6 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
759760 BackendRepr :: Memory { sized : true }
760761 } ;
761762
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-
767763 let layout = LayoutData {
768764 variants : Variants :: Multiple {
769765 tag : niche_scalar,
@@ -856,6 +852,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
856852 let mut align = dl. aggregate_align ;
857853 let mut max_repr_align = repr. align ;
858854 let mut unadjusted_abi_align = align;
855+ let mut combined_seed = repr. field_shuffle_seed ;
859856
860857 let mut size = Size :: ZERO ;
861858
@@ -879,14 +876,13 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
879876
880877 // Create the set of structs that represent each variant.
881878 let mut layout_variants = variants
882- . iter_enumerated ( )
883- . map ( |( i , field_layouts) | {
884- let mut st = self . univariant (
879+ . iter ( )
880+ . map ( |field_layouts| {
881+ let st = self . univariant (
885882 field_layouts,
886883 repr,
887884 StructKind :: Prefixed ( min_ity. size ( ) , prefix_align) ,
888885 ) ?;
889- st. variants = Variants :: Single { index : i } ;
890886 // Find the first field we can't move later
891887 // to make room for a larger discriminant.
892888 for field_idx in st. fields . index_by_increasing_offset ( ) {
@@ -900,7 +896,8 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
900896 align = align. max ( st. align . abi ) ;
901897 max_repr_align = max_repr_align. max ( st. max_repr_align ) ;
902898 unadjusted_abi_align = unadjusted_abi_align. max ( st. unadjusted_abi_align ) ;
903- Ok ( st)
899+ combined_seed = combined_seed. wrapping_add ( st. randomization_seed ) ;
900+ Ok ( VariantLayout :: from_layout ( st) )
904901 } )
905902 . collect :: < Result < IndexVec < VariantIdx , _ > , _ > > ( ) ?;
906903
@@ -955,23 +952,16 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
955952 let old_ity_size = min_ity. size ( ) ;
956953 let new_ity_size = ity. size ( ) ;
957954 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" )
955+ for i in & mut variant. field_offsets {
956+ if * i <= old_ity_size {
957+ assert_eq ! ( * i, old_ity_size) ;
958+ * i = new_ity_size;
973959 }
974960 }
961+ // We might be making the struct larger.
962+ if variant. size <= old_ity_size {
963+ variant. size = new_ity_size;
964+ }
975965 }
976966 }
977967
@@ -996,12 +986,10 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
996986 let mut common_prim = None ;
997987 let mut common_prim_initialized_in_all_variants = true ;
998988 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- } ;
1002989 // We skip *all* ZST here and later check if we are good in terms of alignment.
1003990 // This lets us handle some cases involving aligned ZST.
1004- let mut fields = iter:: zip ( field_layouts, offsets) . filter ( |p| !p. 0 . is_zst ( ) ) ;
991+ let mut fields = iter:: zip ( field_layouts, & layout_variant. field_offsets )
992+ . filter ( |p| !p. 0 . is_zst ( ) ) ;
1005993 let ( field, offset) = match ( fields. next ( ) , fields. next ( ) ) {
1006994 ( None , None ) => {
1007995 common_prim_initialized_in_all_variants = false ;
@@ -1096,25 +1084,17 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
10961084 for variant in & mut layout_variants {
10971085 // We only do this for variants with fields; the others are not accessed anyway.
10981086 // Also do not overwrite any already existing "clever" ABIs.
1099- if variant. fields . count ( ) > 0
1100- && matches ! ( variant. backend_repr, BackendRepr :: Memory { .. } )
1087+ if matches ! ( variant. backend_repr, BackendRepr :: Memory { .. } if variant. has_fields( ) )
11011088 {
11021089 variant. backend_repr = abi;
1103- // Also need to bump up the size and alignment, so that the entire value fits
1104- // in here.
1090+ // Also need to bump up the size, so that the entire value fits in here.
11051091 variant. size = cmp:: max ( variant. size , size) ;
1106- variant. align . abi = cmp:: max ( variant. align . abi , align) ;
11071092 }
11081093 }
11091094 }
11101095
11111096 let largest_niche = Niche :: from_scalar ( dl, Size :: ZERO , tag) ;
11121097
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-
11181098 let tagged_layout = LayoutData {
11191099 variants : Variants :: Multiple {
11201100 tag,
0 commit comments