{"id":"79603b6e96f6ed8c","repo":"rust-lang/rust","slug":"layout-decided-on-a-larger-discriminant-type-min","errorCode":null,"errorMessage":"layout decided on a larger discriminant type ({min_ity:?}) than typeck ({typeck_ity:?})","messagePattern":"layout decided on a larger discriminant type \\((.+?)\\) than typeck \\((.+?)\\)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"compiler/rustc_abi/src/layout.rs","lineNumber":860,"sourceCode":"        size = size.align_to(align);\n\n        // FIXME(oli-obk): deduplicate and harden these checks\n        if size.bytes() >= dl.obj_size_bound() {\n            return Err(LayoutCalculatorError::SizeOverflow);\n        }\n\n        let typeck_ity = Integer::from_attr(dl, repr.discr_type());\n        if typeck_ity < min_ity {\n            // It is a bug if Layout decided on a greater discriminant size than typeck for\n            // some reason at this point (based on values discriminant can take on). Mostly\n            // because this discriminant will be loaded, and then stored into variable of\n            // type calculated by typeck. Consider such case (a bug): typeck decided on\n            // byte-sized discriminant, but layout thinks we need a 16-bit to store all\n            // discriminant values. That would be a bug, because then, in codegen, in order\n            // to store this 16-bit discriminant into 8-bit sized temporary some of the\n            // space necessary to represent would have to be discarded (or layout is wrong\n            // on thinking it needs 16 bits)\n            panic!(\n                \"layout decided on a larger discriminant type ({min_ity:?}) than typeck ({typeck_ity:?})\"\n            );\n            // However, it is fine to make discr type however large (as an optimisation)\n            // after this point – we’ll just truncate the value we load in codegen.\n        }\n\n        // Check to see if we should use a different type for the\n        // discriminant. We can safely use a type with the same size\n        // as the alignment of the first field of each variant.\n        // We increase the size of the discriminant to avoid LLVM copying\n        // padding when it doesn't need to. This normally causes unaligned\n        // load/stores and excessive memcpy/memset operations. By using a\n        // bigger integer size, LLVM can be sure about its contents and\n        // won't be so conservative.\n\n        // Use the initial field alignment\n        let mut ity = if repr.c() || repr.int.is_some() {\n            min_ity","sourceCodeStart":842,"sourceCodeEnd":878,"githubUrl":"https://github.com/rust-lang/rust/blob/22057b88b091743bc0fd8d592a9264f0a6951403/compiler/rustc_abi/src/layout.rs#L842-L878","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: from_attr and layout disagree on discriminant width\n#[repr(u8)]\nenum E { A = 200, B = 300 } // typeck should reject; ICE if not\n\n// fix: choose a repr wide enough for every discriminant value\n#[repr(u16)]\nenum E { A = 200, B = 300 }","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Layout-vs-typeck discriminant mismatch is a compiler-internal bug; the only\n// user-side defense is to isolate layout computation behind catch_unwind.\nuse rustc_abi::LayoutCalculatorError;\n\nlet layout = match std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {\n    // the call that can panic, e.g.:\n    // layout_calculator.layout_of(cx, ty)\n    compute_enum_layout(ty)\n})) {\n    Ok(Ok(l)) => l,                       // normal success\n    Ok(Err(LayoutCalculatorError::SizeOverflow)) => {\n        // a real, expected recoverable error returned by the API\n        return Err(LayoutError::SizeOverflow);\n    }\n    Err(panic_payload) => {\n        // errorIndex 10 lands here: bug in rustc, not user input.\n        log::error!(\"rustc bug: discriminant layout > typeck layout: {panic_payload:?}\");\n        return Err(LayoutError::InternalBug);\n    }\n};","preventionTips":["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."],"tags":["rustc","abi","layout","enum","discriminant","compiler-ice"],"analyzedSha":"22057b88b091743bc0fd8d592a9264f0a6951403","analyzedAt":"2026-08-03T08:09:25.915Z","schemaVersion":2}