@@ -40,6 +40,8 @@ pub trait LayoutCalculator {
4040 largest_niche,
4141 align,
4242 size,
43+ max_repr_align : None ,
44+ unadjusted_abi_align : align. abi ,
4345 }
4446 }
4547
@@ -122,6 +124,8 @@ pub trait LayoutCalculator {
122124 largest_niche : None ,
123125 align : dl. i8_align ,
124126 size : Size :: ZERO ,
127+ max_repr_align : None ,
128+ unadjusted_abi_align : dl. i8_align . abi ,
125129 }
126130 }
127131
@@ -289,13 +293,18 @@ pub trait LayoutCalculator {
289293 }
290294
291295 let mut align = dl. aggregate_align ;
296+ let mut max_repr_align = repr. align ;
297+ let mut unadjusted_abi_align = align. abi ;
298+
292299 let mut variant_layouts = variants
293300 . iter_enumerated ( )
294301 . map ( |( j, v) | {
295302 let mut st = self . univariant ( dl, v, repr, StructKind :: AlwaysSized ) ?;
296303 st. variants = Variants :: Single { index : j } ;
297304
298305 align = align. max ( st. align ) ;
306+ max_repr_align = max_repr_align. max ( st. max_repr_align ) ;
307+ unadjusted_abi_align = unadjusted_abi_align. max ( st. unadjusted_abi_align ) ;
299308
300309 Some ( st)
301310 } )
@@ -422,6 +431,8 @@ pub trait LayoutCalculator {
422431 largest_niche,
423432 size,
424433 align,
434+ max_repr_align,
435+ unadjusted_abi_align,
425436 } ;
426437
427438 Some ( TmpLayout { layout, variants : variant_layouts } )
@@ -456,6 +467,9 @@ pub trait LayoutCalculator {
456467 let ( min_ity, signed) = discr_range_of_repr ( min, max) ; //Integer::repr_discr(tcx, ty, &repr, min, max);
457468
458469 let mut align = dl. aggregate_align ;
470+ let mut max_repr_align = repr. align ;
471+ let mut unadjusted_abi_align = align. abi ;
472+
459473 let mut size = Size :: ZERO ;
460474
461475 // We're interested in the smallest alignment, so start large.
@@ -498,6 +512,8 @@ pub trait LayoutCalculator {
498512 }
499513 size = cmp:: max ( size, st. size ) ;
500514 align = align. max ( st. align ) ;
515+ max_repr_align = max_repr_align. max ( st. max_repr_align ) ;
516+ unadjusted_abi_align = unadjusted_abi_align. max ( st. unadjusted_abi_align ) ;
501517 Some ( st)
502518 } )
503519 . collect :: < Option < IndexVec < VariantIdx , _ > > > ( ) ?;
@@ -691,6 +707,8 @@ pub trait LayoutCalculator {
691707 abi,
692708 align,
693709 size,
710+ max_repr_align,
711+ unadjusted_abi_align,
694712 } ;
695713
696714 let tagged_layout = TmpLayout { layout : tagged_layout, variants : layout_variants } ;
@@ -730,10 +748,7 @@ pub trait LayoutCalculator {
730748 let dl = self . current_data_layout ( ) ;
731749 let dl = dl. borrow ( ) ;
732750 let mut align = if repr. pack . is_some ( ) { dl. i8_align } else { dl. aggregate_align } ;
733-
734- if let Some ( repr_align) = repr. align {
735- align = align. max ( AbiAndPrefAlign :: new ( repr_align) ) ;
736- }
751+ let mut max_repr_align = repr. align ;
737752
738753 // If all the non-ZST fields have the same ABI and union ABI optimizations aren't
739754 // disabled, we can use that common ABI for the union as a whole.
@@ -751,6 +766,7 @@ pub trait LayoutCalculator {
751766 assert ! ( field. 0 . is_sized( ) ) ;
752767
753768 align = align. max ( field. align ( ) ) ;
769+ max_repr_align = max_repr_align. max ( field. max_repr_align ( ) ) ;
754770 size = cmp:: max ( size, field. size ( ) ) ;
755771
756772 if field. 0 . is_zst ( ) {
@@ -787,6 +803,14 @@ pub trait LayoutCalculator {
787803 if let Some ( pack) = repr. pack {
788804 align = align. min ( AbiAndPrefAlign :: new ( pack) ) ;
789805 }
806+ // The unadjusted ABI alignment does not include repr(align), but does include repr(pack).
807+ // See documentation on `LayoutS::unadjusted_abi_align`.
808+ let unadjusted_abi_align = align. abi ;
809+ if let Some ( repr_align) = repr. align {
810+ align = align. max ( AbiAndPrefAlign :: new ( repr_align) ) ;
811+ }
812+ // `align` must not be modified after this, or `unadjusted_abi_align` could be inaccurate.
813+ let align = align;
790814
791815 // If all non-ZST fields have the same ABI, we may forward that ABI
792816 // for the union as a whole, unless otherwise inhibited.
@@ -809,6 +833,8 @@ pub trait LayoutCalculator {
809833 largest_niche : None ,
810834 align,
811835 size : size. align_to ( align. abi ) ,
836+ max_repr_align,
837+ unadjusted_abi_align,
812838 } )
813839 }
814840}
@@ -829,6 +855,7 @@ fn univariant(
829855) -> Option < LayoutS > {
830856 let pack = repr. pack ;
831857 let mut align = if pack. is_some ( ) { dl. i8_align } else { dl. aggregate_align } ;
858+ let mut max_repr_align = repr. align ;
832859 let mut inverse_memory_index: IndexVec < u32 , FieldIdx > = fields. indices ( ) . collect ( ) ;
833860 let optimize = !repr. inhibit_struct_field_reordering_opt ( ) ;
834861 if optimize && fields. len ( ) > 1 {
@@ -997,6 +1024,7 @@ fn univariant(
9971024 } ;
9981025 offset = offset. align_to ( field_align. abi ) ;
9991026 align = align. max ( field_align) ;
1027+ max_repr_align = max_repr_align. max ( field. max_repr_align ( ) ) ;
10001028
10011029 debug ! ( "univariant offset: {:?} field: {:#?}" , offset, field) ;
10021030 offsets[ i] = offset;
@@ -1018,9 +1046,16 @@ fn univariant(
10181046
10191047 offset = offset. checked_add ( field. size ( ) , dl) ?;
10201048 }
1049+
1050+ // The unadjusted ABI alignment does not include repr(align), but does include repr(pack).
1051+ // See documentation on `LayoutS::unadjusted_abi_align`.
1052+ let unadjusted_abi_align = align. abi ;
10211053 if let Some ( repr_align) = repr. align {
10221054 align = align. max ( AbiAndPrefAlign :: new ( repr_align) ) ;
10231055 }
1056+ // `align` must not be modified after this point, or `unadjusted_abi_align` could be inaccurate.
1057+ let align = align;
1058+
10241059 debug ! ( "univariant min_size: {:?}" , offset) ;
10251060 let min_size = offset;
10261061 // As stated above, inverse_memory_index holds field indices by increasing offset.
@@ -1036,6 +1071,7 @@ fn univariant(
10361071 inverse_memory_index. into_iter ( ) . map ( FieldIdx :: as_u32) . collect ( )
10371072 } ;
10381073 let size = min_size. align_to ( align. abi ) ;
1074+ let mut layout_of_single_non_zst_field = None ;
10391075 let mut abi = Abi :: Aggregate { sized } ;
10401076 // Unpack newtype ABIs and find scalar pairs.
10411077 if sized && size. bytes ( ) > 0 {
@@ -1045,6 +1081,8 @@ fn univariant(
10451081 match ( non_zst_fields. next ( ) , non_zst_fields. next ( ) , non_zst_fields. next ( ) ) {
10461082 // We have exactly one non-ZST field.
10471083 ( Some ( ( i, field) ) , None , None ) => {
1084+ layout_of_single_non_zst_field = Some ( field) ;
1085+
10481086 // Field fills the struct and it has a scalar or scalar pair ABI.
10491087 if offsets[ i] . bytes ( ) == 0 && align. abi == field. align ( ) . abi && size == field. size ( )
10501088 {
@@ -1102,13 +1140,28 @@ fn univariant(
11021140 if fields. iter ( ) . any ( |f| f. abi ( ) . is_uninhabited ( ) ) {
11031141 abi = Abi :: Uninhabited ;
11041142 }
1143+
1144+ let unadjusted_abi_align = if repr. transparent ( ) {
1145+ match layout_of_single_non_zst_field {
1146+ Some ( l) => l. unadjusted_abi_align ( ) ,
1147+ None => {
1148+ // `repr(transparent)` with all ZST fields.
1149+ align. abi
1150+ }
1151+ }
1152+ } else {
1153+ unadjusted_abi_align
1154+ } ;
1155+
11051156 Some ( LayoutS {
11061157 variants : Variants :: Single { index : FIRST_VARIANT } ,
11071158 fields : FieldsShape :: Arbitrary { offsets, memory_index } ,
11081159 abi,
11091160 largest_niche,
11101161 align,
11111162 size,
1163+ max_repr_align,
1164+ unadjusted_abi_align,
11121165 } )
11131166}
11141167
0 commit comments