rust-lang/rust · critical
discr subgoal...
Error message
discr subgoal...
What it means
Inside the next trait solver's DiscriminantKind handling (computing <T as DiscriminantKind>::Discriminant), when the self type is ty::UnsafeBinder the code cannot derive a discriminant type and panics with unimplemented!("discr subgoal..."). It is a FIXME(unsafe_binders) placeholder: unsafe binder types are an unstable feature whose interaction with discriminant computation has not been finished.
Solutions
- Do not wrap enum types that need discriminant queries in an unsafe binder; operate on the unwrapped inner type.
- Disable the unsafe_binders feature and use a raw pointer / transmute-based alternative for the unsafe access.
- Switch to the classic trait solver if the code path does not strictly require the next solver.
- Wait for / upstream a fix for the FIXME(unsafe_binders) discriminant subgoal; report on the unsafe_binders tracking issue.
Example fix
// before #![feature(unsafe_binders)] let b: unsafe_binder<'_, Enum> = bind(value); let d = mem::discriminant(&b); // panics: discr subgoal // after: unwrap before querying discriminant let d = mem::discriminant(&value);
Defensive patterns
Strategy: validation
Validate before calling
// Avoid querying discriminants on unsafe-binder-wrapped enum types.
// Validate by not wrapping enums that need DiscriminantKind:
fn needs_discriminant<T>() { let _ = std::mem::discriminant; } Prevention
- Do not wrap enum types in unsafe binders when discriminant semantics are required.
- Disable #![feature(unsafe_binders)] for code that touches enums via discriminants.
- Prefer the classic solver for unsafe-binder experiments.
When it happens
Trigger: Using unsafe binder types (#![feature(unsafe_binders)]) with code that needs the DiscriminantKind impl / discriminant type — e.g. mem::discriminant, match on a value whose type is wrapped in an unsafe binder, or any intrinsic that queries the discriminant type — while running under the next trait solver.
Common situations: Experimental code enabling #![feature(unsafe_binders)] on a recent nightly, especially when the compiler auto-derives DiscriminantKind for enums behind an unsafe binder. Not reachable on stable.
Related errors
- FIXME(unsafe_binder)
- reservation impl for trait with assoc item
- Accessing live loans requires `-Zpolonius=next`
- `async gen` closures not supported yet
- AsyncFn* are not yet const
AI-assisted analysis of rust-lang/rust@7088e4b63a (2026-08-10).
Data as JSON: /api/errors/df2b9d0cb4121fa4.
Report an issue: GitHub.
Appendix: source
Thrown at compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs:1008
| ty::FnDef(..)
| ty::FnPtr(..)
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Infer(ty::IntVar(..) | ty::FloatVar(..))
| ty::Coroutine(..)
| ty::CoroutineWitness(..)
| ty::Never
| ty::Foreign(..)
| ty::Adt(_, _)
| ty::Str
| ty::Slice(_)
| ty::Dynamic(_, _)
| ty::Tuple(_)
| ty::Error(_) => self_ty.discriminant_ty(ecx.cx()),
ty::UnsafeBinder(_) => {
// FIXME(unsafe_binders): instantiate this with placeholders?? i guess??
unimplemented!("discr subgoal...")
}
// Given an alias, parameter, or placeholder we add an impl candidate normalizing to a rigid
// alias. In case there's a where-bound further constraining this alias it is preferred over
// this impl candidate anyways. It's still a bit scuffed.
ty::Alias(ty::IsRigid::Yes, _) | ty::Param(_) | ty::Placeholder(..) => {
return ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| {
ecx.instantiate_normalizes_to_as_rigid(goal)?;
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
});
}
ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_))
| ty::Alias(ty::IsRigid::No, _)
| ty::Bound(..) => panic!(
"unexpected self ty `{:?}` when normalizing `<T as DiscriminantKind>::Discriminant`",
goal.predicate.self_ty()
),View on GitHub (pinned to 7088e4b63a)