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