@@ -1078,60 +1078,72 @@ impl<'a, 'tcx> CachedLayout {
1078
1078
packed
1079
1079
} ;
1080
1080
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 {
1092
1095
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.
1094
1103
Abi :: ScalarPair ( ..) => {
1095
1104
abi = field. abi . clone ( ) ;
1096
1105
}
1097
1106
_ => { }
1098
1107
}
1099
1108
}
1100
1109
}
1101
- _ => { }
1102
- }
1103
- }
1104
- }
1105
1110
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 ;
1119
1142
}
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 ;
1132
1143
}
1144
+
1145
+ _ => { }
1133
1146
}
1134
- _ => { }
1135
1147
}
1136
1148
}
1137
1149
0 commit comments