{"id":"ec2a3193ff4d9fd5","repo":"rust-lang/rust","slug":"encountered-a-non-arbitrary-layout-during-enum-lay","errorCode":null,"errorMessage":"encountered a non-arbitrary layout during enum layout","messagePattern":"encountered a non-arbitrary layout during enum layout","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"compiler/rustc_abi/src/layout.rs","lineNumber":1007,"sourceCode":"                }\n            }\n            if let Some((prim, offset)) = common_prim {\n                let prim_scalar = if common_prim_initialized_in_all_variants {\n                    let size = prim.size(dl);\n                    assert!(size.bits() <= 128);\n                    Scalar::Initialized { value: prim, valid_range: WrappingRange::full(size) }\n                } else {\n                    // Common prim might be uninit.\n                    Scalar::Union { value: prim }\n                };\n                let pair =\n                    LayoutData::<FieldIdx, VariantIdx>::scalar_pair(&self.cx, tag, prim_scalar);\n                let pair_offsets = match pair.fields {\n                    FieldsShape::Arbitrary { ref offsets, ref in_memory_order } => {\n                        assert_eq!(in_memory_order.raw, [FieldIdx::new(0), FieldIdx::new(1)]);\n                        offsets\n                    }\n                    _ => panic!(\"encountered a non-arbitrary layout during enum layout\"),\n                };\n                if pair_offsets[FieldIdx::new(0)] == Size::ZERO\n                    && pair_offsets[FieldIdx::new(1)] == *offset\n                    && align == pair.align.abi\n                    && size == pair.size\n                {\n                    // We can use `ScalarPair` only when it matches our\n                    // already computed layout (including `#[repr(C)]`).\n                    abi = pair.backend_repr;\n                }\n            }\n        }\n\n        // If we pick a \"clever\" (by-value) ABI, we might have to adjust the ABI of the\n        // variants to ensure they are consistent. This is because a downcast is\n        // semantically a NOP, and thus should not affect layout.\n        if matches!(abi, BackendRepr::Scalar(..) | BackendRepr::ScalarPair { .. }) {\n            for variant in &mut layout_variants {","sourceCodeStart":989,"sourceCodeEnd":1025,"githubUrl":"https://github.com/rust-lang/rust/blob/22057b88b091743bc0fd8d592a9264f0a6951403/compiler/rustc_abi/src/layout.rs#L989-L1025","documentation":"Fires in layout_of_enum during the niche/scalar-pair ABI optimization. The code calls LayoutData::scalar_pair and then destructures the resulting fields expecting FieldsShape::Arbitrary with in_memory_order [0,1]; the wildcard arm treats any other shape (Primitive/Array/Union) as unreachable. Hitting it means scalar_pair's documented output invariant was broken, an internal layout corruption.","triggerScenarios":"Reached only if LayoutData::scalar_pair is modified to return a non-Arbitrary FieldsShape, or memory/logic corruption makes pair.fields not match the expected Arbitrary { offsets, in_memory_order: [0, 1] } during enum niche optimization.","commonSituations":"Pure internal compiler bug surfacing as an ICE during enum layout. Typically appears after edits to the rustc_abi scalar-pair constructors or a bad merge in the layout/codegen pipeline; ordinary user programs do not trigger it.","solutions":["Report as an ICE to the Rust repo with a reduced enum that triggers the niche optimization.","As a compiler dev, audit LayoutData::scalar_pair to confirm it still emits FieldsShape::Arbitrary with in_memory_order [0,1].","Bisect to locate the commit that altered scalar-pair field construction."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// 'non-arbitrary layout during enum layout' is an unreachable post-condition\n// of LayoutData::scalar_pair; no input predicate can predict it. Catch it at the\n// boundary where you compute enum ABI layouts.\nlet abi = match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {\n    layout_for_enum(cx, ty)\n})) {\n    Ok(Ok(layout)) => layout,\n    Ok(Err(recoverable)) => return Err(recoverable.into()),\n    Err(payload) => {\n        log::error!(\"rustc bug: scalar_pair did not yield Arbitrary FieldsShape: {payload:?}\");\n        // fall back to the memory (non-ScalarPair) ABI you already computed\n        fallback_memory_abi(ty)\n    }\n};","preventionTips":["This fires only when LayoutData::scalar_pair produces a FieldsShape other than Arbitrary — an internal invariant violation, not something a caller's enum definition can be validated against.","Wrap the enum-layout computation in catch_unwind and degrade gracefully to the already-computed BackendRepr::Memory layout when it triggers.","Do not construct LayoutData fields by hand to feed the layout calculator; obtain them through the normal layout pipeline so scalar_pair's Arbitrary post-condition is preserved.","If reproducible, report to rustc with the enum whose (tag, primitive-payload) niche-pair triggered the ScalarPair attempt."],"tags":["rustc","abi","layout","enum","scalar-pair","compiler-ice"],"analyzedSha":"22057b88b091743bc0fd8d592a9264f0a6951403","analyzedAt":"2026-08-03T08:09:25.915Z","schemaVersion":2}