@@ -41,6 +41,7 @@ pub trait LayoutCalculator {
41
41
align,
42
42
size,
43
43
repr_align : None ,
44
+ unadjusted_abi_align : align. abi ,
44
45
}
45
46
}
46
47
@@ -124,6 +125,7 @@ pub trait LayoutCalculator {
124
125
align : dl. i8_align ,
125
126
size : Size :: ZERO ,
126
127
repr_align : None ,
128
+ unadjusted_abi_align : dl. i8_align . abi ,
127
129
}
128
130
}
129
131
@@ -291,13 +293,16 @@ pub trait LayoutCalculator {
291
293
}
292
294
293
295
let mut align = dl. aggregate_align ;
296
+ let mut unadjusted_abi_align = align. abi ;
297
+
294
298
let mut variant_layouts = variants
295
299
. iter_enumerated ( )
296
300
. map ( |( j, v) | {
297
301
let mut st = self . univariant ( dl, v, repr, StructKind :: AlwaysSized ) ?;
298
302
st. variants = Variants :: Single { index : j } ;
299
303
300
304
align = align. max ( st. align ) ;
305
+ unadjusted_abi_align = unadjusted_abi_align. max ( st. unadjusted_abi_align ) ;
301
306
302
307
Some ( st)
303
308
} )
@@ -425,6 +430,7 @@ pub trait LayoutCalculator {
425
430
size,
426
431
align,
427
432
repr_align : repr. align ,
433
+ unadjusted_abi_align,
428
434
} ;
429
435
430
436
Some ( TmpLayout { layout, variants : variant_layouts } )
@@ -459,6 +465,8 @@ pub trait LayoutCalculator {
459
465
let ( min_ity, signed) = discr_range_of_repr ( min, max) ; //Integer::repr_discr(tcx, ty, &repr, min, max);
460
466
461
467
let mut align = dl. aggregate_align ;
468
+ let mut unadjusted_abi_align = align. abi ;
469
+
462
470
let mut size = Size :: ZERO ;
463
471
464
472
// We're interested in the smallest alignment, so start large.
@@ -501,6 +509,7 @@ pub trait LayoutCalculator {
501
509
}
502
510
size = cmp:: max ( size, st. size ) ;
503
511
align = align. max ( st. align ) ;
512
+ unadjusted_abi_align = unadjusted_abi_align. max ( st. unadjusted_abi_align ) ;
504
513
Some ( st)
505
514
} )
506
515
. collect :: < Option < IndexVec < VariantIdx , _ > > > ( ) ?;
@@ -695,6 +704,7 @@ pub trait LayoutCalculator {
695
704
align,
696
705
size,
697
706
repr_align : repr. align ,
707
+ unadjusted_abi_align,
698
708
} ;
699
709
700
710
let tagged_layout = TmpLayout { layout : tagged_layout, variants : layout_variants } ;
@@ -735,10 +745,6 @@ pub trait LayoutCalculator {
735
745
let dl = dl. borrow ( ) ;
736
746
let mut align = if repr. pack . is_some ( ) { dl. i8_align } else { dl. aggregate_align } ;
737
747
738
- if let Some ( repr_align) = repr. align {
739
- align = align. max ( AbiAndPrefAlign :: new ( repr_align) ) ;
740
- }
741
-
742
748
// If all the non-ZST fields have the same ABI and union ABI optimizations aren't
743
749
// disabled, we can use that common ABI for the union as a whole.
744
750
struct AbiMismatch ;
@@ -791,6 +797,14 @@ pub trait LayoutCalculator {
791
797
if let Some ( pack) = repr. pack {
792
798
align = align. min ( AbiAndPrefAlign :: new ( pack) ) ;
793
799
}
800
+ // The unadjusted ABI alignment does not include repr(align), but does include repr(pack).
801
+ // See documentation on `LayoutS::unadjusted_abi_align`.
802
+ let unadjusted_abi_align = align. abi ;
803
+ if let Some ( repr_align) = repr. align {
804
+ align = align. max ( AbiAndPrefAlign :: new ( repr_align) ) ;
805
+ }
806
+ // `align` must not be modified after this, or `unadjusted_abi_align` could be inaccurate.
807
+ let align = align;
794
808
795
809
// If all non-ZST fields have the same ABI, we may forward that ABI
796
810
// for the union as a whole, unless otherwise inhibited.
@@ -814,6 +828,7 @@ pub trait LayoutCalculator {
814
828
align,
815
829
size : size. align_to ( align. abi ) ,
816
830
repr_align : repr. align ,
831
+ unadjusted_abi_align,
817
832
} )
818
833
}
819
834
}
@@ -1023,9 +1038,16 @@ fn univariant(
1023
1038
1024
1039
offset = offset. checked_add ( field. size ( ) , dl) ?;
1025
1040
}
1041
+
1042
+ // The unadjusted ABI alignment does not include repr(align), but does include repr(pack).
1043
+ // See documentation on `LayoutS::unadjusted_abi_align`.
1044
+ let unadjusted_abi_align = align. abi ;
1026
1045
if let Some ( repr_align) = repr. align {
1027
1046
align = align. max ( AbiAndPrefAlign :: new ( repr_align) ) ;
1028
1047
}
1048
+ // `align` must not be modified after this point, or `unadjusted_abi_align` could be inaccurate.
1049
+ let align = align;
1050
+
1029
1051
debug ! ( "univariant min_size: {:?}" , offset) ;
1030
1052
let min_size = offset;
1031
1053
// As stated above, inverse_memory_index holds field indices by increasing offset.
@@ -1111,9 +1133,29 @@ fn univariant(
1111
1133
abi = Abi :: Uninhabited ;
1112
1134
}
1113
1135
1114
- let repr_align = repr. align . or_else ( || {
1115
- if repr. transparent ( ) { layout_of_single_non_zst_field?. repr_align ( ) } else { None }
1116
- } ) ;
1136
+ let ( repr_align, unadjusted_abi_align) = if repr. transparent ( ) {
1137
+ match layout_of_single_non_zst_field {
1138
+ Some ( l) => ( l. repr_align ( ) , l. unadjusted_abi_align ( ) ) ,
1139
+ None => {
1140
+ // `repr(transparent)` with all ZST fields.
1141
+ //
1142
+ // Using `None` for `repr_align` here is technically incorrect, since one of
1143
+ // the ZSTs could have `repr(align(1))`. It's an interesting question, if you have
1144
+ // `#{repr(transparent)] struct Foo((), ZstWithReprAlign1)`, which of those ZSTs'
1145
+ // ABIs is forwarded by `repr(transparent)`? The answer to that question determines
1146
+ // whether we should use `None` or `Some(align 1)` here. Thanksfully, two things
1147
+ // together mean this doesn't matter:
1148
+ // - You're not allowed to have a `repr(transparent)` struct that contains
1149
+ // `repr(align)` > 1 ZSTs. See error E0691.
1150
+ // - MSVC never treats requested align 1 differently from natural align 1.
1151
+ // (And the `repr_align` field is only used on i686-windows, see `LayoutS` docs.)
1152
+ // So just use `None` for now.
1153
+ ( None , align. abi )
1154
+ }
1155
+ }
1156
+ } else {
1157
+ ( repr. align , unadjusted_abi_align)
1158
+ } ;
1117
1159
1118
1160
Some ( LayoutS {
1119
1161
variants : Variants :: Single { index : FIRST_VARIANT } ,
@@ -1123,6 +1165,7 @@ fn univariant(
1123
1165
align,
1124
1166
size,
1125
1167
repr_align,
1168
+ unadjusted_abi_align,
1126
1169
} )
1127
1170
}
1128
1171
0 commit comments