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
- Confirm the type passed to `const_from_scalar` is fully monomorphized and sized; substitute generic params before calling.
- 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).
- 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.
- 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
- Only synthesize scalar constants for fully-monomorphized, sized, representable types; extern types, unsized types, and types needing recursion-depth layout will fail layout_of.
- Run `tcx.layout_of` yourself before building a scalar constant so a layout error is a handled branch, not a debug-assertion panic.
- Remember this check lives in `debug_assert!`: it is silent in optimized builds but will crash debug builds of rustc/rustdoc/clippy/miri — test your driver in debug mode.
- If you receive a Scalar from external data (e.g. deserialized rmeta), validate both the layout AND the scalar size (see [259]) before constructing the Operand.
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
- Invalid scalar type {val:?}
- range should be nonempty
- there must be provenance somewhere here
- an interpreter error got improperly discarded; use `discard_
- statics should not have generic parameters
AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03).
Data as JSON: /data/errors/1aa3d4d83362ba49.json.
Report an issue: GitHub.