{"id":"9ecd5b5e84138983","repo":"rust-lang/rust","slug":"size-bits-bytes-bytes-in-bits-doesn-t-fit-in-u","errorCode":null,"errorMessage":"Size::bits: {bytes} bytes in bits doesn't fit in u64","messagePattern":"Size::bits: (.+?) bytes in bits doesn't fit in u64","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"compiler/rustc_abi/src/lib.rs","lineNumber":897,"sourceCode":"        let bytes: u64 = bytes.try_into().ok().unwrap();\n        Size { raw: bytes }\n    }\n\n    #[inline]\n    pub fn bytes(self) -> u64 {\n        self.raw\n    }\n\n    #[inline]\n    pub fn bytes_usize(self) -> usize {\n        self.bytes().try_into().unwrap()\n    }\n\n    #[inline]\n    pub fn bits(self) -> u64 {\n        #[cold]\n        fn overflow(bytes: u64) -> ! {\n            panic!(\"Size::bits: {bytes} bytes in bits doesn't fit in u64\")\n        }\n\n        self.bytes().checked_mul(8).unwrap_or_else(|| overflow(self.bytes()))\n    }\n\n    #[inline]\n    pub fn bits_usize(self) -> usize {\n        self.bits().try_into().unwrap()\n    }\n\n    #[inline]\n    pub fn align_to(self, align: Align) -> Size {\n        let mask = align.bytes() - 1;\n        Size::from_bytes((self.bytes() + mask) & !mask)\n    }\n\n    #[inline]\n    pub fn is_aligned(self, align: Align) -> bool {","sourceCodeStart":879,"sourceCodeEnd":915,"githubUrl":"https://github.com/rust-lang/rust/blob/22057b88b091743bc0fd8d592a9264f0a6951403/compiler/rustc_abi/src/lib.rs#L879-L915","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nlet bit_size = layout.size.bits();\n\n// after - use the checked path during layout\nlet Some(size) = layout.checked_add(other, cx) else {\n    return Err(LayoutError::SizeOverflow);\n};\nlet bit_size = size.bits();","handlingStrategy":"validation","validationCode":"// Size::bits() panics when bytes * 8 overflows u64, i.e. bytes > u64::MAX/8.\n// Validate before calling .bits():\nfn safe_bits(size: rustc_abi::Size) -> Option<u64> {\n    const BITS_CAP: u64 = u64::MAX / 8;\n    (size.bytes() <= BITS_CAP).then(|| size.bits())\n}","typeGuard":"// Size is a single struct; no narrower type exists. Guard the value, not the type.\n// Equivalent: prefer checked helpers when a HasDataLayout context is available\n// (checked_add/checked_mul bound against cx.data_layout().obj_size_bound()).\nfn size_is_bit_representable(size: rustc_abi::Size) -> bool {\n    size.bytes().checked_mul(8).is_some()\n}","tryCatchPattern":"// Rust panics are not catchable without catch_unwind; prefer pre-validation.\n// Last-resort pattern:\nuse std::panic::Assertion;\nlet bits = Assertion::catch_unwind(Assertion::always_enabled(), || size.bits())\n    .ok_or_else(|| LayoutError::SizeOverflow)?;","preventionTips":["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."],"tags":["rustc-abi","size","overflow","panic","layout"],"analyzedSha":"22057b88b091743bc0fd8d592a9264f0a6951403","analyzedAt":"2026-08-03T08:09:25.915Z","schemaVersion":2}