match st[i].abi() {
Abi::Scalar(_) => Abi::Scalar(niche_scalar),
Abi::ScalarPair(first, second) => {
- // We need to use scalar_unit to reset the
- // valid range to the maximal one for that
- // primitive, because only the niche is
- // guaranteed to be initialised, not the
- // other primitive.
+ // Only the niche is guaranteed to be initialised,
+ // so use union layout for the other primitive.
if offset.bytes() == 0 {
- Abi::ScalarPair(
- niche_scalar,
- scalar_unit(second.primitive()),
- )
+ Abi::ScalarPair(niche_scalar, second.to_union())
} else {
- Abi::ScalarPair(
- scalar_unit(first.primitive()),
- niche_scalar,
- )
+ Abi::ScalarPair(first.to_union(), niche_scalar)
}
}
_ => Abi::Aggregate { sized: true },
} else {
// Try to use a ScalarPair for all tagged enums.
let mut common_prim = None;
+ let mut common_prim_initialized_in_all_variants = true;
for (field_layouts, layout_variant) in iter::zip(&variants, &layout_variants) {
let FieldsShape::Arbitrary { ref offsets, .. } = layout_variant.fields else {
bug!();
let mut fields =
iter::zip(field_layouts, offsets).filter(|p| !p.0.is_zst());
let (field, offset) = match (fields.next(), fields.next()) {
- (None, None) => continue,
+ (None, None) => {
+ common_prim_initialized_in_all_variants = false;
+ continue;
+ }
(Some(pair), None) => pair,
_ => {
common_prim = None;
}
};
let prim = match field.abi {
- Abi::Scalar(scalar) => scalar.primitive(),
+ Abi::Scalar(scalar) => {
+ common_prim_initialized_in_all_variants &=
+ matches!(scalar, Scalar::Initialized { .. });
+ scalar.primitive()
+ }
_ => {
common_prim = None;
break;
}
}
if let Some((prim, offset)) = common_prim {
- let pair = self.scalar_pair(tag, scalar_unit(prim));
+ let prim_scalar = if common_prim_initialized_in_all_variants {
+ scalar_unit(prim)
+ } else {
+ // Common prim might be uninit.
+ Scalar::Union { value: prim }
+ };
+ let pair = self.scalar_pair(tag, prim_scalar);
let pair_offsets = match pair.fields {
FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
assert_eq!(memory_index, &[0, 1]);
pointee_info
}
+
+ fn is_adt(this: TyAndLayout<'tcx>) -> bool {
+ matches!(this.ty.kind(), ty::Adt(..))
+ }
+
+ fn is_never(this: TyAndLayout<'tcx>) -> bool {
+ this.ty.kind() == &ty::Never
+ }
+
+ fn is_tuple(this: TyAndLayout<'tcx>) -> bool {
+ matches!(this.ty.kind(), ty::Tuple(..))
+ }
+
+ fn is_unit(this: TyAndLayout<'tcx>) -> bool {
+ matches!(this.ty.kind(), ty::Tuple(list) if list.len() == 0)
+ }
}
impl<'tcx> ty::Instance<'tcx> {