Rollup merge of #151040 - moulins:public-variant-layout, r=makai410

Don't expose redundant information in `rustc_public`'s `LayoutShape`

Enum variant layouts don't need to store a full `LayoutShape`; just storing the fields offsets is enough and all other information can be inferred from the parent layout:
- size, align and ABI don't make much sense for individual variants and should generally be taken from the parent layout instead;
- variants always have `fields: FieldsShape::Arbitrary { .. }` and `variant: VariantShape::Single { .. }`.

In principle, the same refactor could be done on `rustc_abi::Layout` (see [this comment](https://github.com/rust-lang/rust/issues/113988#issuecomment-1646982272)) but I prefer starting with this smaller change first.
This commit is contained in:
Stuart Cook 2026-01-27 12:50:52 +11:00 committed by GitHub
commit 957801bf74
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 28 additions and 3 deletions

View file

@ -188,10 +188,27 @@ pub enum VariantsShape {
tag: Scalar,
tag_encoding: TagEncoding,
tag_field: usize,
variants: Vec<LayoutShape>,
variants: Vec<VariantFields>,
},
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)]
pub struct VariantFields {
/// Offsets for the first byte of each field,
/// ordered to match the source definition order.
/// I.e.: It follows the same order as [super::ty::VariantDef::fields()].
/// This vector does not go in increasing order.
pub offsets: Vec<Size>,
}
impl VariantFields {
pub fn fields_by_offset_order(&self) -> Vec<FieldIdx> {
let mut indices = (0..self.offsets.len()).collect::<Vec<_>>();
indices.sort_by_key(|idx| self.offsets[*idx]);
indices
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)]
pub enum TagEncoding {
/// The tag directly stores the discriminant, but possibly with a smaller layout

View file

@ -11,7 +11,7 @@ use rustc_target::callconv;
use crate::abi::{
AddressSpace, ArgAbi, CallConvention, FieldsShape, FloatLength, FnAbi, IntegerLength,
IntegerType, Layout, LayoutShape, PassMode, Primitive, ReprFlags, ReprOptions, Scalar,
TagEncoding, TyAndLayout, ValueAbi, VariantsShape, WrappingRange,
TagEncoding, TyAndLayout, ValueAbi, VariantFields, VariantsShape, WrappingRange,
};
use crate::compiler_interface::BridgeTys;
use crate::target::MachineSize as Size;
@ -213,7 +213,15 @@ impl<'tcx> Stable<'tcx> for rustc_abi::Variants<rustc_abi::FieldIdx, rustc_abi::
tag: tag.stable(tables, cx),
tag_encoding: tag_encoding.stable(tables, cx),
tag_field: tag_field.stable(tables, cx),
variants: variants.iter().as_slice().stable(tables, cx),
variants: variants
.iter()
.map(|v| match &v.fields {
rustc_abi::FieldsShape::Arbitrary { offsets, .. } => VariantFields {
offsets: offsets.iter().as_slice().stable(tables, cx),
},
_ => panic!("variant layout should be Arbitrary"),
})
.collect(),
}
}
}