rust-lang/rust · critical

expected monomorphic const in codegen

Error message

expected monomorphic const in codegen

What it means

This fires in Cranelift codegen when processing `Rvalue::Repeat` (e.g., `[value; N]`). The repeat count `N` is a const that should be monomorphized to a concrete `usize` by codegen time. The code calls `fx.monomorphize(times).try_to_target_usize(fx.tcx).expect(...)`. If after monomorphization the const is still generic, unevaluated, or not a concrete target usize, the conversion fails and panics.

Source

Thrown at compiler/rustc_codegen_cranelift/src/base.rs:845

                Rvalue::Cast(
                    CastKind::Transmute | CastKind::BoxDerefTransmute | CastKind::Subtype,
                    ref operand,
                    _to_ty,
                ) => {
                    let operand = codegen_operand(fx, operand);
                    lval.write_cvalue_transmute(fx, operand);
                }
                Rvalue::Discriminant(place) => {
                    let place = codegen_place(fx, place);
                    let value = place.to_cvalue(fx);
                    crate::discriminant::codegen_get_discriminant(fx, lval, value, dest_layout);
                }
                Rvalue::Repeat(ref operand, times) => {
                    let operand = codegen_operand(fx, operand);
                    let times = fx
                        .monomorphize(times)
                        .try_to_target_usize(fx.tcx)
                        .expect("expected monomorphic const in codegen");
                    if operand.layout().size.bytes() == 0 {
                        // Do nothing for ZST's
                    } else if fx.clif_type(operand.layout().ty) == Some(types::I8) {
                        let times = fx.bcx.ins().iconst(fx.pointer_type, times as i64);
                        // FIXME use emit_small_memset where possible
                        let addr = lval.to_ptr().get_addr(fx);
                        let val = operand.load_scalar(fx);
                        fx.bcx.call_memset(fx.target_config, addr, val, times);
                    } else {
                        let loop_block = fx.bcx.create_block();
                        let loop_block2 = fx.bcx.create_block();
                        let done_block = fx.bcx.create_block();
                        let index = fx.bcx.append_block_param(loop_block, fx.pointer_type);
                        let zero = fx.bcx.ins().iconst(fx.pointer_type, 0);
                        fx.bcx.ins().jump(loop_block, &[zero.into()]);

                        fx.bcx.switch_to_block(loop_block);
                        let done = fx.bcx.ins().icmp_imm_u(IntCC::Equal, index, times as i64);

View on GitHub (pinned to 7088e4b63a)

Solutions

  1. File an ICE bug report — monomorphization should guarantee a concrete const by codegen.
  2. Avoid generic const expressions in array repeat counts; use a runtime `vec![val; count]` or a concrete array size if possible.
  3. Try `-Zmir-opt-level=0` or the LLVM backend to narrow the issue.
  4. If using `generic_const_exprs`, update to the latest nightly — the feature pipeline changes frequently.
  5. If contributing to rustc, verify that mono item collection properly instantiates the const before passing the body to codegen.

Example fix

// before (generic const in array repeat, may reach codegen unevaluated)
fn f<const N: usize>() -> [u32; N] {
    [0; N]
}

// after (use Vec for runtime-size, or concrete size)
fn f<const N: usize>() -> Vec<u32> {
    vec![0; N]
}
Defensive patterns

Strategy: fallback

Validate before calling

// Avoid generic const expressions in array repeat counts
// Type-check at the source level:
// Prefer: const N: usize = 10; [0; N]
// Over:   fn f<const N: usize>() -> [u32; N] { [0; N] }

Type guard

// Ensure array repeat counts are concrete, not generic
fn assert_concrete_array_repeat<T, const N: usize>() {
    // N is generic; [0; N] may fail in codegen on some nightly versions
    // Use Vec instead for generic sizes
}
// Prefer:
fn make_array<const N: usize>() -> Vec<u32> { vec![0; N] }

Prevention

When it happens

Trigger: Codegen encounters a `[val; COUNT]` expression where `COUNT` is a generic const parameter or a const that monomorphization failed to evaluate to a concrete `usize`. In a correctly functioning compiler, all generics are instantiated before codegen, so this const should always be concrete by this point.

Common situations: Using generic const expressions in array repeat syntax (e.g., `[0; N]` where `N` is a generic parameter) in combinations that confuse monomorphization or const-eval. Can also happen with unstable `generic_const_exprs` feature where const evaluation is not yet fully wired through to codegen. Most often a compiler bug rather than user error.

Related errors


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