{"id":"597c7f13acf8f4a7","repo":"rust-lang/rust","slug":"unexpected-root-evaluation-evaluation","errorCode":null,"errorMessage":"unexpected root evaluation: {evaluation:?}","messagePattern":"unexpected root evaluation: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compiler/rustc_next_trait_solver/src/solve/inspect/build.rs","lineNumber":122,"sourceCode":"}\n\nimpl<I: Interner> WipEvaluationStep<I> {\n    fn current_evaluation_scope(&mut self) -> &mut WipProbe<I> {\n        let mut current = &mut self.evaluation;\n        for _ in 0..self.probe_depth {\n            match current.steps.last_mut() {\n                Some(WipProbeStep::NestedProbe(p)) => current = p,\n                _ => panic!(),\n            }\n        }\n        current\n    }\n\n    fn finalize(self) -> inspect::Probe<I> {\n        let evaluation = self.evaluation.finalize();\n        match evaluation.kind {\n            inspect::ProbeKind::Root { .. } => evaluation,\n            _ => unreachable!(\"unexpected root evaluation: {evaluation:?}\"),\n        }\n    }\n}\n\n#[derive_where(PartialEq, Debug; I: Interner)]\nstruct WipProbe<I: Interner> {\n    initial_num_var_values: usize,\n    steps: Vec<WipProbeStep<I>>,\n    kind: Option<inspect::ProbeKind<I>>,\n    final_state: Option<inspect::CanonicalState<I, ()>>,\n}\n\nimpl<I: Interner> Eq for WipProbe<I> {}\n\nimpl<I: Interner> WipProbe<I> {\n    fn finalize(self) -> inspect::Probe<I> {\n        inspect::Probe {\n            steps: self.steps.into_iter().map(WipProbeStep::finalize).collect(),","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/rust-lang/rust/blob/22057b88b091743bc0fd8d592a9264f0a6951403/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs#L104-L140","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// The inspection/build path only expects certain root evaluations. If you drive\n// rustc's `-Z self-profile` / `-Z dump-solver` from CI, gate the dump on known-good\n// evaluation shapes.\nfn dump_config_known_good(cfg: &DumpConfig) -> bool {\n    matches!(cfg.root_evaluation, RootEval::Normal | RootEval::Transparent)\n}\n#[test]\nfn assert_dump_safe() { assert!(dump_config_known_good(&dump_cfg())); }","typeGuard":null,"tryCatchPattern":"use std::panic::{catch_unwind, AssertUnwindSafe};\nlet graph = catch_unwind(AssertUnwindSafe(|| inspect::build_root(evaluation)));\ngraph.ok().unwrap_or_else(inspect::empty_graph)","preventionTips":["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."],"tags":["rust","rustc","trait-solver","ice","next-solver","proof-trees","inspector","debugging"],"analyzedSha":"22057b88b091743bc0fd8d592a9264f0a6951403","analyzedAt":"2026-08-03T08:09:25.915Z","schemaVersion":2}