@@ -1078,60 +1078,72 @@ impl<'a, 'tcx> CachedLayout {
10781078 packed
10791079 } ;
10801080
1081- // Unpack newtype ABIs.
1082- if sized && optimize && size. bytes ( ) > 0 {
1083- // All but one field must be ZSTs, and so they all start at 0.
1084- if offsets. iter ( ) . all ( |o| o. bytes ( ) == 0 ) {
1085- let mut non_zst_fields = fields. iter ( ) . filter ( |f| !f. is_zst ( ) ) ;
1086-
1087- // We have exactly one non-ZST field.
1088- match ( non_zst_fields. next ( ) , non_zst_fields. next ( ) ) {
1089- ( Some ( field) , None ) => {
1090- // Field size matches and it has a scalar or scalar pair ABI.
1091- if size == field. size {
1081+ // Unpack newtype ABIs and find scalar pairs.
1082+ if sized && size. bytes ( ) > 0 {
1083+ // All other fields must be ZSTs, and we need them to all start at 0.
1084+ let mut zst_offsets =
1085+ offsets. iter ( ) . enumerate ( ) . filter ( |& ( i, _) | fields[ i] . is_zst ( ) ) ;
1086+ if zst_offsets. all ( |( _, o) | o. bytes ( ) == 0 ) {
1087+ let mut non_zst_fields =
1088+ fields. iter ( ) . enumerate ( ) . filter ( |& ( _, f) | !f. is_zst ( ) ) ;
1089+
1090+ match ( non_zst_fields. next ( ) , non_zst_fields. next ( ) , non_zst_fields. next ( ) ) {
1091+ // We have exactly one non-ZST field.
1092+ ( Some ( ( i, field) ) , None , None ) => {
1093+ // Field fills the struct and it has a scalar or scalar pair ABI.
1094+ if offsets[ i] . bytes ( ) == 0 && size == field. size {
10921095 match field. abi {
1093- Abi :: Scalar ( _) |
1096+ // For plain scalars we can't unpack newtypes
1097+ // for `#[repr(C)]`, as that affects C ABIs.
1098+ Abi :: Scalar ( _) if optimize => {
1099+ abi = field. abi . clone ( ) ;
1100+ }
1101+ // But scalar pairs are Rust-specific and get
1102+ // treated as aggregates by C ABIs anyway.
10941103 Abi :: ScalarPair ( ..) => {
10951104 abi = field. abi . clone ( ) ;
10961105 }
10971106 _ => { }
10981107 }
10991108 }
11001109 }
1101- _ => { }
1102- }
1103- }
1104- }
11051110
1106- // Look for a scalar pair, as an ABI optimization.
1107- // FIXME(eddyb) ignore extra ZST fields and field ordering.
1108- if sized && !packed && fields. len ( ) == 2 {
1109- match ( & fields[ 0 ] . abi , & fields[ 1 ] . abi ) {
1110- ( & Abi :: Scalar ( ref a) , & Abi :: Scalar ( ref b) ) => {
1111- let pair = scalar_pair ( a. clone ( ) , b. clone ( ) ) ;
1112- let pair_offsets = match pair. fields {
1113- FieldPlacement :: Arbitrary {
1114- ref offsets,
1115- ref memory_index
1116- } => {
1117- assert_eq ! ( memory_index, & [ 0 , 1 ] ) ;
1118- offsets
1111+ // Two non-ZST fields, and they're both scalars.
1112+ ( Some ( ( i, & TyLayout {
1113+ cached : & CachedLayout { abi : Abi :: Scalar ( ref a) , .. } , ..
1114+ } ) ) , Some ( ( j, & TyLayout {
1115+ cached : & CachedLayout { abi : Abi :: Scalar ( ref b) , .. } , ..
1116+ } ) ) , None ) => {
1117+ // Order by the memory placement, not source order.
1118+ let ( ( i, a) , ( j, b) ) = if offsets[ i] < offsets[ j] {
1119+ ( ( i, a) , ( j, b) )
1120+ } else {
1121+ ( ( j, b) , ( i, a) )
1122+ } ;
1123+ let pair = scalar_pair ( a. clone ( ) , b. clone ( ) ) ;
1124+ let pair_offsets = match pair. fields {
1125+ FieldPlacement :: Arbitrary {
1126+ ref offsets,
1127+ ref memory_index
1128+ } => {
1129+ assert_eq ! ( memory_index, & [ 0 , 1 ] ) ;
1130+ offsets
1131+ }
1132+ _ => bug ! ( )
1133+ } ;
1134+ if offsets[ i] == pair_offsets[ 0 ] &&
1135+ offsets[ j] == pair_offsets[ 1 ] &&
1136+ align == pair. align &&
1137+ primitive_align == pair. primitive_align &&
1138+ size == pair. size {
1139+ // We can use `ScalarPair` only when it matches our
1140+ // already computed layout (including `#[repr(C)]`).
1141+ abi = pair. abi ;
11191142 }
1120- _ => bug ! ( )
1121- } ;
1122- if offsets[ 0 ] == pair_offsets[ 0 ] &&
1123- offsets[ 1 ] == pair_offsets[ 1 ] &&
1124- memory_index[ 0 ] == 0 &&
1125- memory_index[ 1 ] == 1 &&
1126- align == pair. align &&
1127- primitive_align == pair. primitive_align &&
1128- size == pair. size {
1129- // We can use `ScalarPair` only when it matches our
1130- // already computed layout (including `#[repr(C)]`).
1131- abi = pair. abi ;
11321143 }
1144+
1145+ _ => { }
11331146 }
1134- _ => { }
11351147 }
11361148 }
11371149
0 commit comments