{"id":"1a31bd165d388367","repo":"rust-lang/rust","slug":"we-never-retry-stalled-queries-if-the-parent-was-e","errorCode":null,"errorMessage":"we never retry stalled queries if the parent was erased","messagePattern":"we never retry stalled queries if the parent was erased","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"compiler/rustc_next_trait_solver/src/solve/eval_ctxt/fast_path.rs","lineNumber":91,"sourceCode":"                .opaque_types_storage_num_entries()\n                .needs_reevaluation(num_opaques_in_storage)\n            {\n                // Unless this goal previously succeeded in erased mode.\n                // If the stalled goal successfully evaluated while erasing opaque types,\n                // and the current state of the opaque type storage is not different in a way that is\n                // relevant, this stalled goal cannot make any progress and we set this variable to true.\n                let mut previous_erased_run_is_still_valid = false;\n\n                if let &SucceededInErased::Yes { accessed_opaques } = previously_succeeded_in_erased\n                {\n                    match should_rerun_after_erased_canonicalization(\n                        accessed_opaques,\n                        delegate.typing_mode_raw(),\n                        &delegate.clone_opaque_types_lookup_table(),\n                    ) {\n                        RerunDecision::Yes => {}\n                        RerunDecision::EagerlyPropagateToParent => {\n                            unreachable!(\"we never retry stalled queries if the parent was erased\")\n                        }\n                        RerunDecision::No => {\n                            previous_erased_run_is_still_valid = true;\n                        }\n                    }\n                }\n\n                if !previous_erased_run_is_still_valid {\n                    return MayMakeProgress;\n                }\n            }\n        }\n    }\n\n    // Otherwise, we can be sure that this stalled goal cannot make any progress\n    // and we can exit early.\n    WontMakeProgress(stalled_certainty)\n}","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/rust-lang/rust/blob/22057b88b091743bc0fd8d592a9264f0a6951403/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/fast_path.rs#L73-L109","documentation":"Internal `unreachable!` invariant assertion in the trait solver's stalled-query fast path (`rerunning_stalled_goal_may_make_progress`). After a stalled goal previously succeeded in erased (opaque-erasing) mode, the solver asks `should_rerun_after_erased_canonicalization` whether to retry; one possible answer is `EagerlyPropagateToParent`, which is only valid in the full `EvalCtxt` path (mod.rs:757) where opaque accesses can be propagated to the parent query. The fast-path cache invariant asserts this never happens for a cached stalled goal — if it does, the stalled-query cache is inconsistent with the typing mode and the compiler ICEs.","triggerScenarios":"Reached when `rerunning_stalled_goal_may_make_progress` re-checks a previously stalled goal whose `previously_succeeded_in_erased == Yes`, the opaque-type storage has changed enough to need reevaluation, the original typing mode is `TypingMode::ErasedNotCoherence(MayBeErased)`, and `should_rerun_after_erased_canonicalization` returns `EagerlyPropagateToParent`. Concretely: heavy opaque-type inference (async blocks, `impl Trait`, RPITs) under `-Znext-solver` where a goal is stalled, partially evaluated in erased mode, then re-probed by the fast path.","commonSituations":"Complex generic code with many `impl Trait`/async opaques compiled with `-Znext-solver`; nightly toolchain regression in the trait solver's opaque-type / erased-canonicalization handling; enabling `-Zdisable-fast-paths` may mask it (it forces `MayMakeProgress`); large monomorphized crates that stress the stalled-query cache.","solutions":["Retry with `-Zdisable-fast-paths` — it short-circuits this fast path and forces the slow path (mod.rs:757) which legitimately handles `EagerlyPropagateToParent`; if that compiles, the bug is fast-path-specific.","Reduce the reproducer by deleting `impl Trait`/async blocks until the ICE vanishes, then report the minimal case upstream as a next-solver ICE.","Bisect nightlies — opaque/erased-canonicalization logic changes frequently in the next solver.","If on a feature branch of rustc, check whether `should_rerun_after_erased_canonicalization` or the stalled-cache population was recently modified; the invariant mismatch is usually a stale `SucceededInErased::Yes` stored where `No` should have been."],"exampleFix":"// before (rustc invocation triggering the ICE)\nrustc -Znext-solver crate_with_heavy_impl_trait\n\n// after — bypass the fast path to confirm and keep compiling while upstream fixes it\nrustc -Znext-solver -Zdisable-fast-paths crate_with_heavy_impl_trait","handlingStrategy":"fallback","validationCode":"// build.rs: detect the trigger pattern (opaque types / impl Trait) in const-adjacent code\n// so you can fall back to explicit named types BEFORE the solver ICEs.\nfn main() {\n    for file in [\"src/lib.rs\"] {\n        let src = std::fs::read_to_string(file).unwrap_or_default();\n        let in_const = src.lines().any(|l| l.contains(\"const fn\") || l.contains(\"const \"));\n        let uses_opaque = src.lines().any(|l| l.contains(\"-> impl \") || l.contains(\"async \"));\n        if in_const && uses_opaque {\n            eprintln!(\"warning: {} mixes `impl Trait`/async with const evaluation; the next-solver can hit the erased-parent ICE (fast_path.rs:91). Replace opaque returns with explicit named types.\", file);\n        }\n    }\n    println!(\"cargo:rerun-if-changed=src/lib.rs\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["This ICE fires when a stalled goal that previously succeeded in erased mode would need `EagerlyPropagateToParent`, which the solver never does for erased parents (fast_path.rs:91). The trigger is opaque-type (`impl Trait`, `async` blocks) inference interacting with const/erased canonicalization.","Primary workaround (fallback): replace `-> impl Trait` return types with explicit named types (a concrete struct, `Box<dyn Trait>`, or a named `type` alias) in any code path near const evaluation.","Avoid nesting `async` blocks / closures that produce opaque types inside generic const code or deep trait-solver recursion.","Pin concrete types instead of leaving heavy inference variables in const-adjacent generic code; the stall/retry path assumes the parent is non-erased.","Debug aid: compile with `-Zdisable-fast-paths` to bypass the fast path and confirm the ICE is fast-path-specific before reporting.","When reporting upstream, include the opaque-type reproducer and the `should_rerun_after_erased_canonicalization` decision path."],"tags":["rustc","trait-solver","opaque-types","ice","fast-path","next-solver"],"analyzedSha":"22057b88b091743bc0fd8d592a9264f0a6951403","analyzedAt":"2026-08-03T08:09:25.915Z","schemaVersion":2}