rust-lang/rust · critical

Size::add: {} + {} doesn't fit in u64

Error message

Size::add: {} + {} doesn't fit in u64

What it means

Thrown by the `Add` impl for `Size` (compiler/rustc_abi/src/lib.rs:990) when `self.bytes() + other.bytes()` overflows u64. The module comment at lib.rs:982-983 explicitly warns: these panicking operators are convenience helpers and must NOT be used during layout computation, where `LayoutError` should be returned instead.

Source

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

    pub fn signed_int_max(&self) -> i128 {
        i128::MAX >> (128 - self.bits())
    }

    #[inline]
    pub fn unsigned_int_max(&self) -> u128 {
        u128::MAX >> (128 - self.bits())
    }
}

// Panicking addition, subtraction and multiplication for convenience.
// Avoid during layout computation, return `LayoutError` instead.

impl Add for Size {
    type Output = Size;
    #[inline]
    fn add(self, other: Size) -> Size {
        Size::from_bytes(self.bytes().checked_add(other.bytes()).unwrap_or_else(|| {
            panic!("Size::add: {} + {} doesn't fit in u64", self.bytes(), other.bytes())
        }))
    }
}

impl Sub for Size {
    type Output = Size;
    #[inline]
    fn sub(self, other: Size) -> Size {
        Size::from_bytes(self.bytes().checked_sub(other.bytes()).unwrap_or_else(|| {
            panic!("Size::sub: {} - {} would result in negative size", self.bytes(), other.bytes())
        }))
    }
}

impl Mul<Size> for u64 {
    type Output = Size;
    #[inline]
    fn mul(self, size: Size) -> Size {

View on GitHub (pinned to 22057b88b0)

Solutions

  1. Replace the `+` operator with `size.checked_add(other, cx)`, which clamps against `data_layout().obj_size_bound()` and returns `Option<Size>`; propagate the `None` as a `LayoutError`.
  2. If the addition is genuinely provably bounded (e.g. two small fixed sizes), keep the operator but add a debug_assert or comment documenting the invariant.
  3. Audit git history for the panic site to find which layout pass introduced the un-checked arithmetic.

Example fix

// before
let total = offset + field_size;

// after
let total = offset.checked_add(field_size, cx)
    .ok_or(LayoutError::SizeOverflow)?;
Defensive patterns

Strategy: validation

Validate before calling

// Size::add panics on overflow. Use checked_add (inherent) or check bytes first.
fn safe_add(a: rustc_abi::Size, b: rustc_abi::Size) -> Option<rustc_abi::Size> {
    a.bytes().checked_add(b.bytes()).map(rustc_abi::Size::from_bytes)
}
// Or, with a layout context, the library helper also bounds against obj_size_bound():
// a.checked_add(b, &cx)

Type guard

// No narrower type; guard the arithmetic result instead.
fn fits_add(a: rustc_abi::Size, b: rustc_abi::Size) -> bool {
    a.bytes().checked_add(b.bytes()).is_some()
}

Try / catch

// Panics here are logic bugs, not recoverable runtime conditions. Do not catch;
// route through checked_add and propagate Option/Result upstream.

Prevention

When it happens

Trigger: Using `size_a + size_b` (the `+` operator) on two `Size` values whose combined byte count exceeds u64::MAX. Common callers are codegen offset arithmetic, niche computation, and any code path that ignores `checked_add`.

Common situations: Hits when porting layout code that previously assumed bounded sizes, or when a backend/helper uses the bare `+` operator on sizes derived from very large array counts or unsized types. Also a regression marker if `obj_size_bound` enforcement was bypassed.

Related errors


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