rust-lang/rust · critical
layout decided on a larger discriminant type ({min_ity:?}) t
Error message
layout decided on a larger discriminant type ({min_ity:?}) than typeck ({typeck_ity:?}) What it means
This panic fires inside LayoutCalculator::layout_of_enum after the minimum integer width needed to represent every enum discriminant value (min_ity) is computed. It asserts that layout never needs more bits than the discriminant type typeck already chose via repr(int)/repr(uN)/repr(iN) (typeck_ity). A violation means codegen would have to truncate a discriminant value that does not fit in typeck's temporary, corrupting enum dispatch — so the compiler aborts rather than emit miscompiling code.
Source
Thrown at compiler/rustc_abi/src/layout.rs:860
size = size.align_to(align);
// FIXME(oli-obk): deduplicate and harden these checks
if size.bytes() >= dl.obj_size_bound() {
return Err(LayoutCalculatorError::SizeOverflow);
}
let typeck_ity = Integer::from_attr(dl, repr.discr_type());
if typeck_ity < min_ity {
// It is a bug if Layout decided on a greater discriminant size than typeck for
// some reason at this point (based on values discriminant can take on). Mostly
// because this discriminant will be loaded, and then stored into variable of
// type calculated by typeck. Consider such case (a bug): typeck decided on
// byte-sized discriminant, but layout thinks we need a 16-bit to store all
// discriminant values. That would be a bug, because then, in codegen, in order
// to store this 16-bit discriminant into 8-bit sized temporary some of the
// space necessary to represent would have to be discarded (or layout is wrong
// on thinking it needs 16 bits)
panic!(
"layout decided on a larger discriminant type ({min_ity:?}) than typeck ({typeck_ity:?})"
);
// However, it is fine to make discr type however large (as an optimisation)
// after this point – we’ll just truncate the value we load in codegen.
}
// Check to see if we should use a different type for the
// discriminant. We can safely use a type with the same size
// as the alignment of the first field of each variant.
// We increase the size of the discriminant to avoid LLVM copying
// padding when it doesn't need to. This normally causes unaligned
// load/stores and excessive memcpy/memset operations. By using a
// bigger integer size, LLVM can be sure about its contents and
// won't be so conservative.
// Use the initial field alignment
let mut ity = if repr.c() || repr.int.is_some() {
min_ityView on GitHub (pinned to 22057b88b0)
Solutions
- If you hit this on unmodified stock rustc, file an ICE at https://github.com/rust-lang/rust/issues with -Zprint-type-sizes output and a minimized enum repro.
- If developing the compiler, confirm Integer::from_attr(dl, repr.discr_type()) and the min_ity loop in layout_of_enum agree on width for the failing enum.
- Temporarily widen or remove the enum's repr(int) annotation to confirm the mismatch originates in the repr-to-integer mapping.
Example fix
// before: from_attr and layout disagree on discriminant width
#[repr(u8)]
enum E { A = 200, B = 300 } // typeck should reject; ICE if not
// fix: choose a repr wide enough for every discriminant value
#[repr(u16)]
enum E { A = 200, B = 300 } Defensive patterns
Strategy: try-catch
Try / catch
// Layout-vs-typeck discriminant mismatch is a compiler-internal bug; the only
// user-side defense is to isolate layout computation behind catch_unwind.
use rustc_abi::LayoutCalculatorError;
let layout = match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
// the call that can panic, e.g.:
// layout_calculator.layout_of(cx, ty)
compute_enum_layout(ty)
})) {
Ok(Ok(l)) => l, // normal success
Ok(Err(LayoutCalculatorError::SizeOverflow)) => {
// a real, expected recoverable error returned by the API
return Err(LayoutError::SizeOverflow);
}
Err(panic_payload) => {
// errorIndex 10 lands here: bug in rustc, not user input.
log::error!("rustc bug: discriminant layout > typeck layout: {panic_payload:?}");
return Err(LayoutError::InternalBug);
}
}; Prevention
- This panic is an internal rustc invariant (see the 'It is a bug' comment at layout.rs:851); it cannot be prevented by validating user types — pin to a released stable rustc and wrap enum-layout calls in catch_unwind at your ABI consumer boundary.
- When hit, file a rustc issue with a minimized enum definition, its #[repr(...)] attribute, explicit discriminant values, and the variant payload types, so typeck and layout agree on discriminant width.
- Avoid hand-crafted #[repr(C)] / #[repr(int)] enums whose declared discriminant type is narrower than the range spanned by the variant discriminant values.
- Separate the two failure modes this call site exposes: the API's real recoverable error (LayoutCalculatorError::SizeOverflow, returned via Result) versus this panic (a bug) — only the latter needs catch_unwind.
When it happens
Trigger: Compiling an enum whose discriminant value range, after layout's exhaustive/niche analysis, requires a wider integer than Integer::from_attr(dl, repr.discr_type()) returns — e.g. a #[repr(u8)] enum whose values cannot be held in 8 bits once layout re-derives the minimum type. In practice only reachable if the from_attr and min_ity computations disagree, since typeck normally rejects too-small repr types first.
Common situations: Almost exclusively a compiler-developer ICE when modifying discriminant logic, merging a bad change to Integer::from_attr, or running an exotic target data layout where the integer resolution differs. Stock user code cannot reach it because typeck gates repr sizes beforehand.
Related errors
- encountered a non-arbitrary layout during enum layout
- aggregates can't have `FieldsShape::Primitive`
- Expected multi-variant layout in `Layout::for_variant`
- a multi-variant layout should have `Arbitrary` fields
- obj_size_bound: unknown pointer bit size {bits}
AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03).
Data as JSON: /data/errors/79603b6e96f6ed8c.json.
Report an issue: GitHub.