{"id":"8cc68f6dbfca5fc8","repo":"rust-lang/rust","slug":"layout-of-fields-should-be-arbitrary-for-variants","errorCode":null,"errorMessage":"Layout of fields should be Arbitrary for variants","messagePattern":"Layout of fields should be Arbitrary for variants","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"compiler/rustc_abi/src/lib.rs","lineNumber":2390,"sourceCode":"    NoExplicitUnwind,\n}\n\n// NOTE: This struct is generic over the FieldIdx and VariantIdx for rust-analyzer usage.\n#[derive(PartialEq, Eq, Hash, Clone, Debug)]\n#[cfg_attr(feature = \"nightly\", derive(StableHash))]\npub struct VariantLayout<FieldIdx: Idx> {\n    pub size: Size,\n    pub backend_repr: BackendRepr,\n    pub field_offsets: IndexVec<FieldIdx, Size>,\n    fields_in_memory_order: IndexVec<u32, FieldIdx>,\n    largest_niche: Option<Niche>,\n    uninhabited: bool,\n}\n\nimpl<FieldIdx: Idx> VariantLayout<FieldIdx> {\n    pub fn from_layout(layout: LayoutData<FieldIdx, impl Idx>) -> Self {\n        let FieldsShape::Arbitrary { offsets, in_memory_order } = layout.fields else {\n            panic!(\"Layout of fields should be Arbitrary for variants\");\n        };\n\n        Self {\n            size: layout.size,\n            backend_repr: layout.backend_repr,\n            field_offsets: offsets,\n            fields_in_memory_order: in_memory_order,\n            largest_niche: layout.largest_niche,\n            uninhabited: layout.uninhabited,\n        }\n    }\n\n    pub fn is_uninhabited(&self) -> bool {\n        self.uninhabited\n    }\n\n    pub fn has_fields(&self) -> bool {\n        self.field_offsets.len() > 0","sourceCodeStart":2372,"sourceCodeEnd":2408,"githubUrl":"https://github.com/rust-lang/rust/blob/22057b88b091743bc0fd8d592a9264f0a6951403/compiler/rustc_abi/src/lib.rs#L2372-L2408","documentation":"Thrown by `VariantLayout::from_layout` at compiler/rustc_abi/src/lib.rs:2390. An enum variant must lay out its fields with explicit offsets, i.e. `FieldsShape::Arbitrary`. The constructor destructures the layout assuming `Arbitrary { offsets, in_memory_order }`; any other `FieldsShape` (`Primitive`, `Union`, `Array`) is structurally incompatible with how variants are represented, so building a `VariantLayout` from one is a logic error.","triggerScenarios":"Passing a `LayoutData` whose `fields` is not `FieldsShape::Arbitrary` into `VariantLayout::from_layout`. This occurs when a caller reuses a single struct/array layout path to construct variant layouts, or when a layout-calculator bug assigns a non-`Arbitrary` shape to a variant.","commonSituations":"Wrong code path in a layout engine that handles structs and enum variants together without separating them; rust-analyzer or miri replaying layouts they constructed themselves; or a refactor that stopped running the variant-specific field-shape assignment (the pass that converts a variant's fields into `Arbitrary { offsets, in_memory_order }`).","solutions":["Before calling `VariantLayout::from_layout`, ensure the variant's fields were passed through the layout pass that produces `FieldsShape::Arbitrary` (struct-like offset assignment).","Add a debug assertion / pattern check on `layout.fields` upstream of this call so a mis-shaped layout is caught where it is produced, not where it is consumed.","If the layout genuinely cannot be `Arbitrary` (e.g. a zero-field unit-like variant), special-case it before reaching `from_layout` rather than forcing a `Union`/`Primitive` shape through."],"exampleFix":"// before\nlet variant = VariantLayout::from_layout(layout);\n\n// after\nlet FieldsShape::Arbitrary { offsets, in_memory_order } = &layout.fields else {\n    bug!(\"variant {variant_idx:?} got non-Arbitrary field shape {:?}\", layout.fields);\n};\n// ...or ensure the layout calculator always assigns Arbitrary to variants.","handlingStrategy":"type-guard","validationCode":"// VariantLayout::from_layout requires FieldsShape::Arbitrary. Match first.\nfn try_variant_layout<FieldIdx: rustc_index::Idx>(\n    layout: rustc_abi::LayoutData<FieldIdx, impl rustc_index::Idx>,\n) -> Result<rustc_abi::VariantLayout<FieldIdx>, &'static str> {\n    match &layout.fields {\n        rustc_abi::FieldsShape::Arbitrary { .. } =>\n            Ok(rustc_abi::VariantLayout::from_layout(layout)),\n        _ => Err(\"VariantLayout requires FieldsShape::Arbitrary\"),\n    }\n}","typeGuard":"fn fields_are_arbitrary<FieldIdx: rustc_index::Idx>(\n    layout: &rustc_abi::LayoutData<FieldIdx, impl rustc_index::Idx>,\n) -> bool {\n    matches!(layout.fields, rustc_abi::FieldsShape::Arbitrary { .. })\n}","tryCatchPattern":"// Panic by design; converting it to a Result via the wrapper above is the\n// recommended pattern. Do not rely on catch_unwind.","preventionTips":["Variants only make sense when each field has its own offset (Arbitrary); Union/Array/Primitive shapes cannot back a variant.","Before calling VariantLayout::from_layout, ensure the LayoutData was produced by the layouter for an enum/struct, not an array or union.","If you accept LayoutData from an external source, validate the FieldsShape variant in the same match you validate size/align."],"tags":["rustc-abi","variantlayout","fieldsshape","invariant","panic","layout","enum"],"analyzedSha":"22057b88b091743bc0fd8d592a9264f0a6951403","analyzedAt":"2026-08-03T08:09:25.915Z","schemaVersion":2}