rust-lang/rust · critical

encountered a non-arbitrary layout during enum layout

Error message

encountered a non-arbitrary layout during enum layout

What it means

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.

Source

Thrown at compiler/rustc_abi/src/layout.rs:1007

                }
            }
            if let Some((prim, offset)) = common_prim {
                let prim_scalar = if common_prim_initialized_in_all_variants {
                    let size = prim.size(dl);
                    assert!(size.bits() <= 128);
                    Scalar::Initialized { value: prim, valid_range: WrappingRange::full(size) }
                } else {
                    // Common prim might be uninit.
                    Scalar::Union { value: prim }
                };
                let pair =
                    LayoutData::<FieldIdx, VariantIdx>::scalar_pair(&self.cx, tag, prim_scalar);
                let pair_offsets = match pair.fields {
                    FieldsShape::Arbitrary { ref offsets, ref in_memory_order } => {
                        assert_eq!(in_memory_order.raw, [FieldIdx::new(0), FieldIdx::new(1)]);
                        offsets
                    }
                    _ => panic!("encountered a non-arbitrary layout during enum layout"),
                };
                if pair_offsets[FieldIdx::new(0)] == Size::ZERO
                    && pair_offsets[FieldIdx::new(1)] == *offset
                    && align == pair.align.abi
                    && size == pair.size
                {
                    // We can use `ScalarPair` only when it matches our
                    // already computed layout (including `#[repr(C)]`).
                    abi = pair.backend_repr;
                }
            }
        }

        // If we pick a "clever" (by-value) ABI, we might have to adjust the ABI of the
        // variants to ensure they are consistent. This is because a downcast is
        // semantically a NOP, and thus should not affect layout.
        if matches!(abi, BackendRepr::Scalar(..) | BackendRepr::ScalarPair { .. }) {
            for variant in &mut layout_variants {

View on GitHub (pinned to 22057b88b0)

Solutions

  1. Report as an ICE to the Rust repo with a reduced enum that triggers the niche optimization.
  2. As a compiler dev, audit LayoutData::scalar_pair to confirm it still emits FieldsShape::Arbitrary with in_memory_order [0,1].
  3. Bisect to locate the commit that altered scalar-pair field construction.
Defensive patterns

Strategy: try-catch

Try / catch

// 'non-arbitrary layout during enum layout' is an unreachable post-condition
// of LayoutData::scalar_pair; no input predicate can predict it. Catch it at the
// boundary where you compute enum ABI layouts.
let abi = match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
    layout_for_enum(cx, ty)
})) {
    Ok(Ok(layout)) => layout,
    Ok(Err(recoverable)) => return Err(recoverable.into()),
    Err(payload) => {
        log::error!("rustc bug: scalar_pair did not yield Arbitrary FieldsShape: {payload:?}");
        // fall back to the memory (non-ScalarPair) ABI you already computed
        fallback_memory_abi(ty)
    }
};

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03). Data as JSON: /data/errors/ec2a3193ff4d9fd5.json. Report an issue: GitHub.