rust-lang/rust · critical

unexpected orig_value: {ct:?}

Error message

unexpected orig_value: {ct:?}

What it means

Const-typed counterpart of the orig_value invariant in EvalCtxt::build_stalled_on. When categorizing stalled const generic args, the only legal ConstKinds are Infer (stalls), and Param/Placeholder (no-op). Any other ConstKind (Value, Alias, Error, Bound, Expr) reaching this point means an unexpected const survived into the stalled-variable set, breaking the assumption that stalled consts are inference variables.

Source

Thrown at compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs:871

    ) -> GoalStalledOn<I> {
        // Remove the canonicalized universal vars, since we only care about stalled existentials.
        let mut sub_roots = ThinVec::new();
        stalled_vars.retain(|arg| match arg.kind() {
            // Lifetimes can never stall goals.
            ty::GenericArgKind::Lifetime(_) => false,
            ty::GenericArgKind::Type(ty) => match ty.kind() {
                ty::Infer(ty::TyVar(vid)) => {
                    sub_roots.push(self.delegate.sub_unification_table_root_var(vid));
                    true
                }
                ty::Infer(_) => true,
                ty::Param(_) | ty::Placeholder(_) => false,
                _ => unreachable!("unexpected orig_value: {ty:?}"),
            },
            ty::GenericArgKind::Const(ct) => match ct.kind() {
                ty::ConstKind::Infer(_) => true,
                ty::ConstKind::Param(_) | ty::ConstKind::Placeholder(_) => false,
                _ => unreachable!("unexpected orig_value: {ct:?}"),
            },
        });

        GoalStalledOn {
            stalled_vars,
            sub_roots,
            stalled_certainty: certainty,
            opaques: GoalStalledOnOpaques::Yes {
                num_opaques_in_storage: canonical_goal
                    .canonical
                    .value
                    .predefined_opaques_in_body
                    .len(),
                previously_succeeded_in_erased,
            },
        }
    }

View on GitHub (pinned to 22057b88b0)

Solutions

  1. Report the ICE with the {ct:?} const printed by the panic message.
  2. Reduce the test case to a minimal const-generic example and attach it to the rustc issue.
  3. Disable -Znext-solver to unblock the build.
  4. If developing the solver, check that const orig_values are normalized/evaluated before stalled-vars are computed so only Infer consts remain.
Defensive patterns

Strategy: type-guard

Validate before calling

// Reject unevaluated/bare const values before they reach the solver.
fn const_arg_is_evaluable(ct: &ConstExpr) -> bool {
    matches!(ct, ConstExpr::Lit(_) | ConstExpr::Path(_))
}
// use in a build.rs / lint pass over generic arguments

Type guard

trait RigidConstArg { fn is_rigid(&self) -> bool; }
impl RigidConstArg for ConstValue {
    fn is_rigid(&self) -> bool { !matches!(self.kind, ConstKind::Unevaluated(_) | ConstKind::Infer(_)) }
}

Try / catch

use std::panic::{catch_unwind, AssertUnwindSafe};
let v = catch_unwind(AssertUnwindSafe(|| compute_const(ct)));
v.unwrap_or_else(|_| ConstValue::zero_sized_fallback())

Prevention

When it happens

Trigger: Hit when build_stalled_on in compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs:868 processes a GenericArgKind::Const whose kind is not Infer/Param/Placeholder — e.g. an unevaluated Alias const or a Value const improperly retained in stalled_vars.

Common situations: ICE triggered while solving const-dependent goals (array lengths, const generics) under -Znext-solver. Usually a compiler regression in const handling or canonicalization rather than a user-code defect.

Related errors


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