rust-lang/rust · error
unexpected root evaluation: {evaluation:?}
Error message
unexpected root evaluation: {evaluation:?} What it means
Proof-tree builder invariant. WipEvaluationStep::finalize expects the finalized probe to be of kind inspect::ProbeKind::Root; any other ProbeKind is unreachable because an evaluation step always starts at a root probe. Hitting it means the proof-tree builder's probe bookkeeping (probe_depth / steps) got out of sync and finalized a non-root probe as if it were the root.
Source
Thrown at compiler/rustc_next_trait_solver/src/solve/inspect/build.rs:122
}
impl<I: Interner> WipEvaluationStep<I> {
fn current_evaluation_scope(&mut self) -> &mut WipProbe<I> {
let mut current = &mut self.evaluation;
for _ in 0..self.probe_depth {
match current.steps.last_mut() {
Some(WipProbeStep::NestedProbe(p)) => current = p,
_ => panic!(),
}
}
current
}
fn finalize(self) -> inspect::Probe<I> {
let evaluation = self.evaluation.finalize();
match evaluation.kind {
inspect::ProbeKind::Root { .. } => evaluation,
_ => unreachable!("unexpected root evaluation: {evaluation:?}"),
}
}
}
#[derive_where(PartialEq, Debug; I: Interner)]
struct WipProbe<I: Interner> {
initial_num_var_values: usize,
steps: Vec<WipProbeStep<I>>,
kind: Option<inspect::ProbeKind<I>>,
final_state: Option<inspect::CanonicalState<I, ()>>,
}
impl<I: Interner> Eq for WipProbe<I> {}
impl<I: Interner> WipProbe<I> {
fn finalize(self) -> inspect::Probe<I> {
inspect::Probe {
steps: self.steps.into_iter().map(WipProbeStep::finalize).collect(),View on GitHub (pinned to 22057b88b0)
Solutions
- Report the ICE; it only occurs with inspection enabled, so include the flags used.
- Run without -Zverbose-internals / proof-tree inspection to avoid the buggy path.
- Audit new_evaluation_step / finalize_evaluation_step calls to ensure the root probe's kind is set before finalize().
- Bisect changes to the inspect/build.rs probe tracking.
Defensive patterns
Strategy: validation
Validate before calling
// The inspection/build path only expects certain root evaluations. If you drive
// rustc's `-Z self-profile` / `-Z dump-solver` from CI, gate the dump on known-good
// evaluation shapes.
fn dump_config_known_good(cfg: &DumpConfig) -> bool {
matches!(cfg.root_evaluation, RootEval::Normal | RootEval::Transparent)
}
#[test]
fn assert_dump_safe() { assert!(dump_config_known_good(&dump_cfg())); } Try / catch
use std::panic::{catch_unwind, AssertUnwindSafe};
let graph = catch_unwind(AssertUnwindSafe(|| inspect::build_root(evaluation)));
graph.ok().unwrap_or_else(inspect::empty_graph) Prevention
- Don't enable `-Zdump-solver-tree` / `-Zprint-type-size` in normal CI; these inspection paths are diagnostic-only and ICE more often than the main pipeline.
- Pin the toolchain used for any inspection dump — these APIs churn every nightly.
- File the ICE with `-Zdump-mir` off, then re-run with it on only if a maintainer asks.
When it happens
Trigger: Triggered only when proof-tree inspection is enabled (e.g. -Zverbose-internals, -Ztrait-solver=inspect, or debugger-driven evaluation) and EvaluationStepBuilder::finalize (compiler/rustc_next_trait_solver/src/solve/inspect/build.rs:118) is called on a WipEvaluationStep whose top-level probe was not assigned ProbeKind::Root.
Common situations: ICE seen while debugging the new solver or running tools that consume proof trees (rust-analyzer, -Ztimings, custom analyzers). Indicates a bug in the inspector's probe enter/leave logic rather than user code.
Related errors
- this never happens at the root, we're never in erased mode h
- unexpected orig_value: {ty:?}
- unexpected orig_value: {ct:?}
- ConstEquate should not be emitted when `-Znext-solver` is ac
- unexpected nested goal in `relate`: {p:?}
AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03).
Data as JSON: /data/errors/597c7f13acf8f4a7.json.
Report an issue: GitHub.