rust-lang/rust · error

FieldsShape::offset: `Primitive`s have no fields

Error message

FieldsShape::offset: `Primitive`s have no fields

What it means

Marked `unreachable!` at compiler/rustc_abi/src/lib.rs:1694 inside `FieldsShape::offset`. `FieldsShape::Primitive` represents scalar types and `!`, which by definition have no fields; asking for the offset of field `i` is therefore a logic error in the caller. The other variants (`Union`, `Array`, `Arbitrary`) all yield a real offset.

Source

Thrown at compiler/rustc_abi/src/lib.rs:1694

    },
}

impl<FieldIdx: Idx> FieldsShape<FieldIdx> {
    #[inline]
    pub fn count(&self) -> usize {
        match *self {
            FieldsShape::Primitive => 0,
            FieldsShape::Union(count) => count.get(),
            FieldsShape::Array { count, .. } => count.try_into().unwrap(),
            FieldsShape::Arbitrary { ref offsets, .. } => offsets.len(),
        }
    }

    #[inline]
    pub fn offset(&self, i: usize) -> Size {
        match *self {
            FieldsShape::Primitive => {
                unreachable!("FieldsShape::offset: `Primitive`s have no fields")
            }
            FieldsShape::Union(count) => {
                assert!(i < count.get(), "tried to access field {i} of union with {count} fields");
                Size::ZERO
            }
            FieldsShape::Array { stride, count } => {
                let i = u64::try_from(i).unwrap();
                assert!(i < count, "tried to access field {i} of array with {count} fields");
                stride * i
            }
            FieldsShape::Arbitrary { ref offsets, .. } => offsets[FieldIdx::new(i)],
        }
    }

    /// Gets source indices of the fields by increasing offsets.
    #[inline]
    pub fn index_by_increasing_offset(&self) -> impl ExactSizeIterator<Item = usize> {
        // Primitives don't really have fields in the way that structs do,

View on GitHub (pinned to 22057b88b0)

Solutions

  1. Short-circuit on `FieldsShape::Primitive` before iterating fields: `if matches!(fields, FieldsShape::Primitive) { return; }`.
  2. Use `fields.count()` (which returns 0 for `Primitive`) to guard the loop so no offset is ever requested.
  3. If you genuinely expected a fielded layout here, the upstream layout computation is wrong — the type should not have been assigned `Primitive`; investigate why `compute().backend_repr` classified it as scalar.

Example fix

// before
for i in 0..fields.count() {
    let off = fields.offset(i);
    ...
}

// after
if matches!(fields, FieldsShape::Primitive) {
    return; // scalars and ! have no fields
}
for i in 0..fields.count() {
    let off = fields.offset(i);
    ...
}
Defensive patterns

Strategy: type-guard

Validate before calling

// FieldsShape::offset panics for Primitive variants. Branch on the variant first.
fn field_offset(shape: &rustc_abi::FieldsShape, i: usize) -> Option<rustc_abi::Size> {
    match shape {
        rustc_abi::FieldsShape::Primitive => None,
        rustc_abi::FieldsShape::Union(_) => Some(rustc_abi::Size::ZERO),
        rustc_abi::FieldsShape::Array { stride, count } => {
            let i = u64::try_from(i).ok()?;
            (i < *count).then(|| *stride * i)
        }
        rustc_abi::FieldsShape::Arbitrary { offsets, .. } => Some(offsets[rustc_field_idx(i)]),
    }
}

Type guard

fn has_fields(shape: &rustc_abi::FieldsShape) -> bool {
    !matches!(shape, rustc_abi::FieldsShape::Primitive)
}

Try / catch

// unreachable! by design; do not catch. Treat reaching offset() on Primitive as
// a caller bug to be fixed by the type guard above.

Prevention

When it happens

Trigger: Calling `fields.offset(i)` (or any consumer that iterates fields) on a layout whose `FieldsShape` is `Primitive` — i.e. a scalar or `!`-typed value. Reached when field-iteration code does not first check `matches!(fields, FieldsShape::Primitive)` or `fields.count() == 0`.

Common situations: Codegen or debug-info passes that walk fields uniformly across all types without short-circuiting scalars; rust-analyzer or other tools replaying layouts; or generic field-walking helpers shared between struct and scalar layouts.

Related errors


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