Align::from_bytes(repr_align, repr_align).unwrap());
}
+ let optimize = !def.repr.inhibit_union_abi_opt();
let mut size = Size::ZERO;
+ let mut abi = Abi::Aggregate { sized: true };
let index = VariantIdx::new(0);
for field in &variants[index] {
assert!(!field.is_unsized());
} else {
align = align.max(field.align);
}
+
+ // If all non-ZST fields have the same ABI, forward this ABI
+ if optimize && !field.is_zst() {
+ // Normalize scalar_unit to the maximal valid range
+ let field_abi = match &field.abi {
+ Abi::Scalar(x) => Abi::Scalar(scalar_unit(x.value)),
+ Abi::ScalarPair(x, y) => {
+ Abi::ScalarPair(
+ scalar_unit(x.value),
+ scalar_unit(y.value),
+ )
+ }
+ Abi::Vector { element: x, count } => {
+ Abi::Vector {
+ element: scalar_unit(x.value),
+ count: *count,
+ }
+ }
+ Abi::Uninhabited |
+ Abi::Aggregate { .. } => Abi::Aggregate { sized: true },
+ };
+
+ if size == Size::ZERO {
+ // first non ZST: initialize 'abi'
+ abi = field_abi;
+ } else if abi != field_abi {
+ // different fields have different ABI: reset to Aggregate
+ abi = Abi::Aggregate { sized: true };
+ }
+ }
+
size = cmp::max(size, field.size);
}
return Ok(tcx.intern_layout(LayoutDetails {
variants: Variants::Single { index },
fields: FieldPlacement::Union(variants[index].len()),
- abi: Abi::Aggregate { sized: true },
+ abi,
align,
size: size.abi_align(align)
}));
/// Type size "skeleton", i.e. the only information determining a type's size.
/// While this is conservative, (aside from constant sizes, only pointers,
/// newtypes thereof and null pointer optimized enums are allowed), it is
-/// enough to statically check common usecases of transmute.
+/// enough to statically check common use cases of transmute.
#[derive(Copy, Clone, Debug)]
pub enum SizeSkeleton<'tcx> {
/// Any statically computable Layout.
outer_exclusive_binder: ty::DebruijnIndex,
}
+// `TyS` is used a lot. Make sure it doesn't unintentionally get bigger.
+#[cfg(target_arch = "x86_64")]
+static_assert!(MEM_SIZE_OF_TY_S: ::std::mem::size_of::<TyS<'_>>() == 32);
+
impl<'tcx> Ord for TyS<'tcx> {
fn cmp(&self, other: &TyS<'tcx>) -> Ordering {
self.sty.cmp(&other.sty)
pub fn inhibit_struct_field_reordering_opt(&self) -> bool {
!(self.flags & ReprFlags::IS_UNOPTIMISABLE).is_empty() || (self.pack == 1)
}
+
+ /// Returns true if this `#[repr()]` should inhibit union abi optimisations
+ pub fn inhibit_union_abi_opt(&self) -> bool {
+ self.c()
+ }
+
}
impl<'a, 'gcx, 'tcx> AdtDef {
}
#[inline]
- pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> GenericPredicates<'gcx> {
+ pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Lrc<GenericPredicates<'gcx>> {
tcx.predicates_of(self.did)
}
def_id: sized_trait,
substs: tcx.mk_substs_trait(ty, &[])
}).to_predicate();
- let predicates = tcx.predicates_of(self.did).predicates;
- if predicates.into_iter().any(|(p, _)| p == sized_predicate) {
+ let predicates = &tcx.predicates_of(self.did).predicates;
+ if predicates.iter().any(|(p, _)| *p == sized_predicate) {
vec![]
} else {
vec![ty]
/// Represents the various closure traits in the Rust language. This
/// will determine the type of the environment (`self`, in the
-/// desuaring) argument that the closure expects.
+/// desugaring) argument that the closure expects.
///
/// You can get the environment type of a closure using
/// `tcx.closure_env_ty()`.