@@ -11,7 +11,7 @@ use tracing::{debug, trace};
1111use crate :: {
1212 AbiAlign , Align , BackendRepr , FieldsShape , HasDataLayout , IndexSlice , IndexVec , Integer ,
1313 LayoutData , Niche , NonZeroUsize , Primitive , ReprOptions , Scalar , Size , StructKind , TagEncoding ,
14- TargetDataLayout , Variants , WrappingRange ,
14+ TargetDataLayout , VariantLayout , Variants , WrappingRange ,
1515} ;
1616
1717mod coroutine;
@@ -575,6 +575,10 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
575575 }
576576
577577 let calculate_niche_filling_layout = || -> Option < LayoutData < FieldIdx , VariantIdx > > {
578+ struct VariantLayoutInfo {
579+ align_abi : Align ,
580+ }
581+
578582 if repr. inhibit_enum_layout_opt ( ) {
579583 return None ;
580584 }
@@ -586,26 +590,35 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
586590 let mut align = dl. aggregate_align ;
587591 let mut max_repr_align = repr. align ;
588592 let mut unadjusted_abi_align = align;
593+ let mut combined_seed = repr. field_shuffle_seed ;
594+
595+ let mut largest_variant_size = Size :: ZERO ;
596+ let mut largest_variant_index = VariantIdx :: new ( 0 ) ;
597+ let mut largest_variant_niche = None ;
589598
599+ let mut variants_info = IndexVec :: < VariantIdx , _ > :: with_capacity ( variants. len ( ) ) ;
590600 let mut variant_layouts = variants
591601 . iter_enumerated ( )
592- . map ( |( j, v) | {
593- let mut st = self . univariant ( v, repr, StructKind :: AlwaysSized ) . ok ( ) ?;
594- st. variants = Variants :: Single { index : j } ;
602+ . map ( |( i, v) | {
603+ let st = self . univariant ( v, repr, StructKind :: AlwaysSized ) . ok ( ) ?;
604+
605+ variants_info. push ( VariantLayoutInfo { align_abi : st. align . abi } ) ;
606+
607+ if st. size > largest_variant_size {
608+ largest_variant_index = i;
609+ largest_variant_size = st. size ;
610+ largest_variant_niche = st. largest_niche ;
611+ }
595612
596613 align = align. max ( st. align . abi ) ;
597614 max_repr_align = max_repr_align. max ( st. max_repr_align ) ;
598615 unadjusted_abi_align = unadjusted_abi_align. max ( st. unadjusted_abi_align ) ;
616+ combined_seed = combined_seed. wrapping_add ( st. randomization_seed ) ;
599617
600- Some ( st )
618+ Some ( VariantLayout :: from_layout ( st ) )
601619 } )
602620 . collect :: < Option < IndexVec < VariantIdx , _ > > > ( ) ?;
603621
604- let largest_variant_index = variant_layouts
605- . iter_enumerated ( )
606- . max_by_key ( |( _i, layout) | layout. size . bytes ( ) )
607- . map ( |( i, _layout) | i) ?;
608-
609622 let all_indices = variants. indices ( ) ;
610623 let needs_disc =
611624 |index : VariantIdx | index != largest_variant_index && !absent ( & variants[ index] ) ;
@@ -616,42 +629,33 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
616629 ( niche_variants. end ( ) . index ( ) as u128 - niche_variants. start ( ) . index ( ) as u128 ) + 1 ;
617630
618631 // Use the largest niche in the largest variant.
619- let niche = variant_layouts [ largest_variant_index ] . largest_niche ?;
632+ let niche = largest_variant_niche ?;
620633 let ( niche_start, niche_scalar) = niche. reserve ( dl, count) ?;
621634 let niche_offset = niche. offset ;
622635 let niche_size = niche. value . size ( dl) ;
623- let size = variant_layouts [ largest_variant_index ] . size . align_to ( align) ;
636+ let size = largest_variant_size . align_to ( align) ;
624637
625638 let all_variants_fit = variant_layouts. iter_enumerated_mut ( ) . all ( |( i, layout) | {
626639 if i == largest_variant_index {
627640 return true ;
628641 }
629642
630- layout. largest_niche = None ;
631-
632643 if layout. size <= niche_offset {
633644 // This variant will fit before the niche.
634645 return true ;
635646 }
636647
637648 // Determine if it'll fit after the niche.
638- let this_align = layout . align . abi ;
649+ let this_align = variants_info [ i ] . align_abi ;
639650 let this_offset = ( niche_offset + niche_size) . align_to ( this_align) ;
640651
641652 if this_offset + layout. size > size {
642653 return false ;
643654 }
644655
645656 // It'll fit, but we need to make some adjustments.
646- match layout. fields {
647- FieldsShape :: Arbitrary { ref mut offsets, .. } => {
648- for offset in offsets. iter_mut ( ) {
649- * offset += this_offset;
650- }
651- }
652- FieldsShape :: Primitive | FieldsShape :: Array { .. } | FieldsShape :: Union ( ..) => {
653- panic ! ( "Layout of fields should be Arbitrary for variants" )
654- }
657+ for offset in layout. field_offsets . iter_mut ( ) {
658+ * offset += this_offset;
655659 }
656660
657661 // It can't be a Scalar or ScalarPair because the offset isn't 0.
@@ -673,7 +677,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
673677 . iter_enumerated ( )
674678 . all ( |( i, layout) | i == largest_variant_index || layout. size == Size :: ZERO ) ;
675679 let same_size = size == variant_layouts[ largest_variant_index] . size ;
676- let same_align = align == variant_layouts [ largest_variant_index] . align . abi ;
680+ let same_align = align == variants_info [ largest_variant_index] . align_abi ;
677681
678682 let uninhabited = variant_layouts. iter ( ) . all ( |v| v. is_uninhabited ( ) ) ;
679683 let abi = if same_size && same_align && others_zst {
@@ -696,11 +700,6 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
696700 BackendRepr :: Memory { sized : true }
697701 } ;
698702
699- let combined_seed = variant_layouts
700- . iter ( )
701- . map ( |v| v. randomization_seed )
702- . fold ( repr. field_shuffle_seed , |acc, seed| acc. wrapping_add ( seed) ) ;
703-
704703 let layout = LayoutData {
705704 variants : Variants :: Multiple {
706705 tag : niche_scalar,
@@ -793,6 +792,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
793792 let mut align = dl. aggregate_align ;
794793 let mut max_repr_align = repr. align ;
795794 let mut unadjusted_abi_align = align;
795+ let mut combined_seed = repr. field_shuffle_seed ;
796796
797797 let mut size = Size :: ZERO ;
798798
@@ -816,14 +816,13 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
816816
817817 // Create the set of structs that represent each variant.
818818 let mut layout_variants = variants
819- . iter_enumerated ( )
820- . map ( |( i , field_layouts) | {
821- let mut st = self . univariant (
819+ . iter ( )
820+ . map ( |field_layouts| {
821+ let st = self . univariant (
822822 field_layouts,
823823 repr,
824824 StructKind :: Prefixed ( min_ity. size ( ) , prefix_align) ,
825825 ) ?;
826- st. variants = Variants :: Single { index : i } ;
827826 // Find the first field we can't move later
828827 // to make room for a larger discriminant.
829828 for field_idx in st. fields . index_by_increasing_offset ( ) {
@@ -837,7 +836,8 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
837836 align = align. max ( st. align . abi ) ;
838837 max_repr_align = max_repr_align. max ( st. max_repr_align ) ;
839838 unadjusted_abi_align = unadjusted_abi_align. max ( st. unadjusted_abi_align ) ;
840- Ok ( st)
839+ combined_seed = combined_seed. wrapping_add ( st. randomization_seed ) ;
840+ Ok ( VariantLayout :: from_layout ( st) )
841841 } )
842842 . collect :: < Result < IndexVec < VariantIdx , _ > , _ > > ( ) ?;
843843
@@ -892,23 +892,16 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
892892 let old_ity_size = min_ity. size ( ) ;
893893 let new_ity_size = ity. size ( ) ;
894894 for variant in & mut layout_variants {
895- match variant. fields {
896- FieldsShape :: Arbitrary { ref mut offsets, .. } => {
897- for i in offsets {
898- if * i <= old_ity_size {
899- assert_eq ! ( * i, old_ity_size) ;
900- * i = new_ity_size;
901- }
902- }
903- // We might be making the struct larger.
904- if variant. size <= old_ity_size {
905- variant. size = new_ity_size;
906- }
907- }
908- FieldsShape :: Primitive | FieldsShape :: Array { .. } | FieldsShape :: Union ( ..) => {
909- panic ! ( "encountered a non-arbitrary layout during enum layout" )
895+ for i in & mut variant. field_offsets {
896+ if * i <= old_ity_size {
897+ assert_eq ! ( * i, old_ity_size) ;
898+ * i = new_ity_size;
910899 }
911900 }
901+ // We might be making the struct larger.
902+ if variant. size <= old_ity_size {
903+ variant. size = new_ity_size;
904+ }
912905 }
913906 }
914907
@@ -933,12 +926,10 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
933926 let mut common_prim = None ;
934927 let mut common_prim_initialized_in_all_variants = true ;
935928 for ( field_layouts, layout_variant) in iter:: zip ( variants, & layout_variants) {
936- let FieldsShape :: Arbitrary { ref offsets, .. } = layout_variant. fields else {
937- panic ! ( "encountered a non-arbitrary layout during enum layout" ) ;
938- } ;
939929 // We skip *all* ZST here and later check if we are good in terms of alignment.
940930 // This lets us handle some cases involving aligned ZST.
941- let mut fields = iter:: zip ( field_layouts, offsets) . filter ( |p| !p. 0 . is_zst ( ) ) ;
931+ let mut fields = iter:: zip ( field_layouts, & layout_variant. field_offsets )
932+ . filter ( |p| !p. 0 . is_zst ( ) ) ;
942933 let ( field, offset) = match ( fields. next ( ) , fields. next ( ) ) {
943934 ( None , None ) => {
944935 common_prim_initialized_in_all_variants = false ;
@@ -1033,25 +1024,17 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
10331024 for variant in & mut layout_variants {
10341025 // We only do this for variants with fields; the others are not accessed anyway.
10351026 // Also do not overwrite any already existing "clever" ABIs.
1036- if variant. fields . count ( ) > 0
1037- && matches ! ( variant. backend_repr, BackendRepr :: Memory { .. } )
1027+ if matches ! ( variant. backend_repr, BackendRepr :: Memory { .. } if variant. has_fields( ) )
10381028 {
10391029 variant. backend_repr = abi;
1040- // Also need to bump up the size and alignment, so that the entire value fits
1041- // in here.
1030+ // Also need to bump up the size, so that the entire value fits in here.
10421031 variant. size = cmp:: max ( variant. size , size) ;
1043- variant. align . abi = cmp:: max ( variant. align . abi , align) ;
10441032 }
10451033 }
10461034 }
10471035
10481036 let largest_niche = Niche :: from_scalar ( dl, Size :: ZERO , tag) ;
10491037
1050- let combined_seed = layout_variants
1051- . iter ( )
1052- . map ( |v| v. randomization_seed )
1053- . fold ( repr. field_shuffle_seed , |acc, seed| acc. wrapping_add ( seed) ) ;
1054-
10551038 let tagged_layout = LayoutData {
10561039 variants : Variants :: Multiple {
10571040 tag,
0 commit comments