{"id":"132f6434a31f620e","repo":"rust-lang/rust","slug":"constequate-should-not-be-emitted-when-znext-sol","errorCode":null,"errorMessage":"ConstEquate should not be emitted when `-Znext-solver` is active","messagePattern":"ConstEquate should not be emitted when `-Znext-solver` is active","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs","lineNumber":935,"sourceCode":"                    ecx.compute_unstable_feature_goal(param_env, symbol)?\n                }\n                ty::PredicateKind::Subtype(predicate) => {\n                    ecx.compute_subtype_goal(Goal { param_env, predicate })?\n                }\n                ty::PredicateKind::Coerce(predicate) => {\n                    ecx.compute_coerce_goal(Goal { param_env, predicate })?\n                }\n                ty::PredicateKind::DynCompatible(trait_def_id) => {\n                    ecx.compute_dyn_compatible_goal(trait_def_id)?\n                }\n                ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {\n                    ecx.compute_well_formed_goal(Goal { param_env, predicate: term })?\n                }\n                ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(ct)) => {\n                    ecx.compute_const_evaluatable_goal(Goal { param_env, predicate: ct })?\n                }\n                ty::PredicateKind::ConstEquate(_, _) => {\n                    panic!(\"ConstEquate should not be emitted when `-Znext-solver` is active\")\n                }\n                ty::PredicateKind::NormalizesTo(predicate) => {\n                    ecx.compute_normalizes_to_goal(Goal { param_env, predicate })?\n                }\n                ty::PredicateKind::Ambiguous => {\n                    ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS)?\n                }\n            })\n        })\n    }\n\n    // Recursively evaluates all the goals added to this `EvalCtxt` to completion, returning\n    // the certainty of all the goals.\n    #[instrument(level = \"trace\", skip(self))]\n    pub(super) fn try_evaluate_added_goals(\n        &mut self,\n    ) -> Result<Certainty, NoSolutionOrRerunNonErased> {\n        for _ in 0..FIXPOINT_STEP_LIMIT {","sourceCodeStart":917,"sourceCodeEnd":953,"githubUrl":"https://github.com/rust-lang/rust/blob/22057b88b091743bc0fd8d592a9264f0a6951403/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs#L917-L953","documentation":"The next trait solver intentionally does not implement ConstEquate (a predicate the old solver emits when unifying two unevaluated consts). evaluate_added_goals_and_make_canonical_response's goal dispatch hits PredicateKind::ConstEquate and panics, because under -Znext-solver const equality is handled via ConstEvaluatable/normalization instead. Reaching this panic means old-solver code constructed a ConstEquate predicate and routed it into the new solver.","triggerScenarios":"Triggered when the new solver's compute_goal dispatch (compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs:934) receives a ty::PredicateKind::ConstEquate(_, _) predicate. This happens when type-checking code that still emits ConstEquate (e.g. certain array-pattern / const-equality unifications) runs while -Znext-solver is active.","commonSituations":"ICE seen on code that equates generic consts (array sizes, const generics in patterns) when the compiler is built/run with -Znext-solver but a code path wasn't migrated off ConstEquate. Common during rustc development when toggling the solver on for more crates.","solutions":["Report the ICE; include the source location that constructed the ConstEquate predicate (visible in the backtrace).","Migrate the offending type-checking call site to emit ConstEvaluatable/normalization goals instead of ConstEquate.","As an end-user workaround, turn off -Znext-solver until the emitter path is fixed.","Gate the triggering crate off the new solver with -Znext-solver=coherence or the crate-level solver selector."],"exampleFix":"// before (old-solver emission leaking into next-solver)\nself.tcx().predicate_must_hold(modulo_regions, ObligationCause::new(span, ConstEquate(a, b)));\n\n// after (route through ConstEvaluatable / normalization)\nself.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)?;","handlingStrategy":"validation","validationCode":"// Block builds that combine `ConstEquate`-emitting patterns with the next solver.\nfn next_solver_active() -> bool {\n    std::env::var(\"RUSTFLAGS\").unwrap_or_default().contains(\"next-solver\")\n        || std::env::var(\"CARGO_ENCODED_RUSTFLAGS\").unwrap_or_default().contains(\"next-solver\")\n}\nfn const_equate_pattern_used(src: &str) -> bool {\n    // crude: a where-clause of the form `N = M` on const params emits ConstEquate\n    src.contains(\"<const N: usize>\") && src.contains(\"where\")\n        && src.split('=').count() > 1\n}\n#[test]\nfn no_const_equate_with_next_solver() {\n    assert!(!(next_solver_active() && const_equate_pattern_used(include_str!(\"lib.rs\"))));\n}","typeGuard":null,"tryCatchPattern":"use std::panic::{catch_unwind, AssertUnwindSafe};\nlet out = catch_unwind(AssertUnwindSafe(|| run_typeck(crate_ast)));\nif out.is_err() { eprintln!(\"ConstEquate + next-solver conflict; rebuild without -Znext-solver\"); std::process::exit(101); }","preventionTips":["Never combine `const N: usize = M` equality bounds with `-Znext-solver` — pick one solver and stay there.","Set `RUSTFLAGS=\"\"` explicitly in CI for crates that use const-equality, so a global nightly profile can't sneak `-Znext-solver` in.","Document in your crate's README which solver it assumes; this is a global, implicit dependency."],"tags":["rust","rustc","trait-solver","ice","next-solver","const-generics","const-equate"],"analyzedSha":"22057b88b091743bc0fd8d592a9264f0a6951403","analyzedAt":"2026-08-03T08:09:25.915Z","schemaVersion":2}