rust-lang/rust · critical
Size::bits: {bytes} bytes in bits doesn't fit in u64
Error message
Size::bits: {bytes} bytes in bits doesn't fit in u64 What it means
Thrown by `Size::bits()` (compiler/rustc_abi/src/lib.rs:897) when multiplying the stored byte count by 8 overflows u64. `Size` holds a raw byte count as `u64`; converting to bits via `bytes * 8` is only valid for sizes below ~2^61 bytes. This panic signals an absurd/corrupted `Size` value rather than a normal runtime condition, since no real object approaches that magnitude.
Source
Thrown at compiler/rustc_abi/src/lib.rs:897
let bytes: u64 = bytes.try_into().ok().unwrap();
Size { raw: bytes }
}
#[inline]
pub fn bytes(self) -> u64 {
self.raw
}
#[inline]
pub fn bytes_usize(self) -> usize {
self.bytes().try_into().unwrap()
}
#[inline]
pub fn bits(self) -> u64 {
#[cold]
fn overflow(bytes: u64) -> ! {
panic!("Size::bits: {bytes} bytes in bits doesn't fit in u64")
}
self.bytes().checked_mul(8).unwrap_or_else(|| overflow(self.bytes()))
}
#[inline]
pub fn bits_usize(self) -> usize {
self.bits().try_into().unwrap()
}
#[inline]
pub fn align_to(self, align: Align) -> Size {
let mask = align.bytes() - 1;
Size::from_bytes((self.bytes() + mask) & !mask)
}
#[inline]
pub fn is_aligned(self, align: Align) -> bool {View on GitHub (pinned to 22057b88b0)
Solutions
- Trace where the oversized `Size` originated — it is almost certainly produced by an earlier unchecked arithmetic op; switch that producer to the checked variants (`checked_add`/`checked_mul` with a `HasDataLayout`) which return `Option<Size>` and propagate `LayoutError` instead of panicking.
- Guard at construction: validate the input to `Size::from_bytes` / `from_bits` against `cx.data_layout().obj_size_bound()` before creating the `Size`.
- If you control the caller of `bits()`, prefer operating in bytes (the stored representation) and only convert to bits once you have established the size is bounded.
Example fix
// before
let bit_size = layout.size.bits();
// after - use the checked path during layout
let Some(size) = layout.checked_add(other, cx) else {
return Err(LayoutError::SizeOverflow);
};
let bit_size = size.bits(); Defensive patterns
Strategy: validation
Validate before calling
// Size::bits() panics when bytes * 8 overflows u64, i.e. bytes > u64::MAX/8.
// Validate before calling .bits():
fn safe_bits(size: rustc_abi::Size) -> Option<u64> {
const BITS_CAP: u64 = u64::MAX / 8;
(size.bytes() <= BITS_CAP).then(|| size.bits())
} Type guard
// Size is a single struct; no narrower type exists. Guard the value, not the type.
// Equivalent: prefer checked helpers when a HasDataLayout context is available
// (checked_add/checked_mul bound against cx.data_layout().obj_size_bound()).
fn size_is_bit_representable(size: rustc_abi::Size) -> bool {
size.bytes().checked_mul(8).is_some()
} Try / catch
// Rust panics are not catchable without catch_unwind; prefer pre-validation.
// Last-resort pattern:
use std::panic::Assertion;
let bits = Assertion::catch_unwind(Assertion::always_enabled(), || size.bits())
.ok_or_else(|| LayoutError::SizeOverflow)?; Prevention
- Never call .bits() on a Size derived from untrusted/externally computed byte counts; cap inputs at u64::MAX/8.
- Prefer the library's checked_add(cx)/checked_mul(cx) variants, which validate against obj_size_bound() before returning a Size.
- Treat any Size produced by raw from_bytes(user_u64) as untrusted until bounded by a HasDataLayout.
When it happens
Trigger: Calling `size.bits()` on a `Size` constructed from an astronomically large byte value (e.g. `Size::from_bytes(u64::MAX)` or a value derived from overflowing unsized-type metadata arithmetic). It is reached through `sign_extend`, `truncate`, `signed_int_min/max`, and `unsigned_int_max`, all of which call `bits()` internally.
Common situations: Corrupted or uninitialized `Size` from a malformed layout computation, a bug in custom codegen backends that hand-build `Size` values, or arithmetic on `usize`-typed unsized sizes that has already overflowed upstream. Almost never seen in front-end compiles; surfaces in fuzzing or when a backend constructs sizes from untrusted metadata.
Related errors
- Size::add: {} + {} 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/9ecd5b5e84138983.json.
Report an issue: GitHub.