rust-lang/rust · error

alt layout should have a niche like the regular one

Error message

alt layout should have a niche like the regular one

What it means

Companion invariant to error 241 (layout.rs:303). Once the end-biased alt layout is computed, the code expects it to have a largest_niche via .expect("alt layout should have a niche like the regular one"). The invariant: biasing the niche to the end does not eliminate the niche that the regular layout had. A panic here is a rustc internal bug in the niche-finding logic.

Solutions

  1. File a rustc ICE report with the minimized type definition and repr attributes.
  2. Remove niched fields and #[repr(...)] to avoid the biased-niche recomputation path.
  3. Bisect with cargo bisect-rustc and compare stable vs nightly.
  4. Reorder fields so the default niche position already satisfies the bias heuristic.
Defensive patterns

Strategy: fallback

Prevention

When it happens

Trigger: Same multi-field, niche-bearing struct/enum path as error 241, where univariant_biased succeeds but its computed layout has largest_niche == None while the regular layout had one.

Common situations: Nightly ICE triggered by niche + repr combinations where end-biasing loses the niche; a layout-algorithm regression.

Related errors


AI-assisted analysis of rust-lang/rust@7088e4b63a (2026-08-10). Data as JSON: /api/errors/ec35c701de775a5b. Report an issue: GitHub.

Appendix: source

Thrown at compiler/rustc_abi/src/layout.rs:303

            // Don't try to calculate an end-biased layout for unsizable structs,
            // otherwise we could end up with different layouts for
            // Foo<Type> and Foo<dyn Trait> which would break unsizing.
            if !matches!(kind, StructKind::MaybeUnsized) {
                if let Some(niche) = layout.largest_niche {
                    let head_space = niche.offset.bytes();
                    let niche_len = niche.value.size(dl).bytes();
                    let tail_space = layout.size.bytes() - head_space - niche_len;

                    // This may end up doing redundant work if the niche is already in the last
                    // field (e.g. a trailing bool) and there is tail padding. But it's non-trivial
                    // to get the unpadded size so we try anyway.
                    if fields.len() > 1 && head_space != 0 && tail_space > 0 {
                        let alt_layout = self
                            .univariant_biased(fields, repr, kind, NicheBias::End)
                            .expect("alt layout should always work");
                        let alt_niche = alt_layout
                            .largest_niche
                            .expect("alt layout should have a niche like the regular one");
                        let alt_head_space = alt_niche.offset.bytes();
                        let alt_niche_len = alt_niche.value.size(dl).bytes();
                        let alt_tail_space =
                            alt_layout.size.bytes() - alt_head_space - alt_niche_len;

                        debug_assert_eq!(layout.size.bytes(), alt_layout.size.bytes());

                        let prefer_alt_layout =
                            alt_head_space > head_space && alt_head_space > tail_space;

                        debug!(
                            "sz: {}, default_niche_at: {}+{}, default_tail_space: {}, alt_niche_at/head_space: {}+{}, alt_tail: {}, num_fields: {}, better: {}\n\
                            layout: {}\n\
                            alt_layout: {}\n",
                            layout.size.bytes(),
                            head_space,
                            niche_len,
                            tail_space,

View on GitHub (pinned to 7088e4b63a)