rust-lang/rust · critical

could not compute layout for {ty:?}: {e:?}

Error message

could not compute layout for {ty:?}: {e:?}

What it means

`Operand::const_from_scalar` has a debug-only assertion that calls `tcx.layout_of(ty)` under a fully-monomorphized `TypingEnv` and panics if it returns Err. rustc_middle throws this to catch codegen/const-eval paths that build a scalar constant for a type whose layout cannot be computed (e.g. unsized, recursive, or not-yet-monomorphized types). Because it sits inside `debug_assert!`, this only fires on debug builds of the compiler.

Source

Thrown at compiler/rustc_middle/src/mir/statement.rs:666

    }

    pub fn is_move(&self) -> bool {
        matches!(self, Operand::Move(..))
    }

    /// Convenience helper to make a literal-like constant from a given scalar value.
    /// Since this is used to synthesize MIR, assumes `user_ty` is None.
    pub fn const_from_scalar(
        tcx: TyCtxt<'tcx>,
        ty: Ty<'tcx>,
        val: Scalar,
        span: Span,
    ) -> Operand<'tcx> {
        debug_assert!({
            let typing_env = ty::TypingEnv::fully_monomorphized();
            let type_size = tcx
                .layout_of(typing_env.as_query_input(ty))
                .unwrap_or_else(|e| panic!("could not compute layout for {ty:?}: {e:?}"))
                .size;
            let scalar_size = match val {
                Scalar::Int(int) => int.size(),
                _ => panic!("Invalid scalar type {val:?}"),
            };
            scalar_size == type_size
        });
        Operand::Constant(Box::new(ConstOperand {
            span,
            user_ty: None,
            const_: Const::Val(ConstValue::Scalar(val), ty),
        }))
    }

    pub fn to_copy(&self) -> Self {
        match *self {
            Operand::Copy(_) | Operand::Constant(_) | Operand::RuntimeChecks(_) => self.clone(),
            Operand::Move(place) => Operand::Copy(place),

View on GitHub (pinned to 22057b88b0)

Solutions

  1. Confirm the type passed to `const_from_scalar` is fully monomorphized and sized; substitute generic params before calling.
  2. If you only see this on a debug rustc, also test on a release build to confirm whether the assertion is the only problem (release will skip it but may ICE later).
  3. In your own backend/pass, gate `const_from_scalar` behind a `layout_of` probe and route layout-less types elsewhere instead of relying on the assert.
  4. Report an ICE against rustc with the failing type, attaching the layout error (`{e:?}`) and the call site.

Example fix

// before
let op = Operand::const_from_scalar(tcx, ty, val, span);
// debug rustc panic: could not compute layout for Generic<T>: ...

// after: substitute / monomorphize first
let mono_ty = ty.subst(tcx, concrete_args);
assert!(tcx.layout_of(typing_env.as_query_input(mono_ty)).is_ok());
let op = Operand::const_from_scalar(tcx, mono_ty, val, span);
Defensive patterns

Strategy: validation

Validate before calling

// const_from_scalar() computes layout_of(ty) and panics if it errors.
// (It is wrapped in debug_assert!, so it bites debug builds / assertions-on builds.)
// Pre-compute the layout and skip scalar const construction if it can't be laid out.
use rustc_middle::ty::{self, Ty, TyCtxt, TypingEnv};
fn ty_has_layout<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
    let typing_env = TypingEnv::fully_monomorphized();
    tcx.layout_of(typing_env.as_query_input(ty)).is_ok()
}
// Usage:
//   if ty_has_layout(tcx, ty) {
//       Operand::const_from_scalar(tcx, ty, scalar, span)
//   } else {
//       // type is not sized/representable: synthesize via const-eval instead
//   }

Try / catch

// Guard the whole scalar-const synthesis so an opaque layout failure degrades gracefully.
use std::panic::{catch_unwind, AssertUnwindSafe};
let operand = catch_unwind(AssertUnwindSafe(|| {
    Operand::const_from_scalar(tcx, ty, scalar, span)
}));
match operand {
    Ok(op) => op,
    Err(_payload) => {
        // layout could not be computed: fall back to an evaluated/unreduced constant
        // rather than feeding a scalar whose size we cannot verify.
        Operand::Constant(Box::new(ConstOperand { span, user_ty: None, const_: Const::Ty(ty, err_const) }))
    }
}

Prevention

When it happens

Trigger: Triggered in a debug rustc build when a caller invokes `const_from_scalar(tcx, ty, val, span)` with a `ty` for which `tcx.layout_of` errors under `TypingEnv::fully_monomorphized()` — e.g. a generic type whose monomorphization is incomplete, an unsized type, or a type with a cycle/error in its layout computation.

Common situations: Building/using a debug (non-release) rustc to compile code that synthesizes scalar constants; const-eval or mir-opt test that passes an errorful/generic type; out-of-tree codegen backend that calls `const_from_scalar` with the wrong type; regression where a normalization step is skipped.

Related errors


AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03). Data as JSON: /data/errors/1aa3d4d83362ba49.json. Report an issue: GitHub.