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
- 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`.
- 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.
- 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
- Avoid the `+` operator on Size entirely during layout computation; the source comment explicitly says: 'Avoid during layout computation, return LayoutError instead.'
- Use checked_add(offset, &cx) which additionally enforces the target obj_size_bound().
- Keep offset accumulators in u64 and validate once before constructing the final Size.
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
- Size::bits: {bytes} bytes in bits doesn't fit in u64
- Size::mul: {} * {} doesn't fit in u64
- Size::sub: {} - {} would result in negative size
- cannot change the valid range of a union
- Layout of fields should be Arbitrary for variants
AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03).
Data as JSON: /data/errors/68cdb750c0da177e.json.
Report an issue: GitHub.