rust-lang/rust · critical
unexpected type `{self_ty:?}`
Error message
unexpected type `{self_ty:?}` What it means
In the trait-goal `consider_builtin_try_as_dyn_candidate` (trait_goals.rs:911), the match on `self_ty.kind()` panics for `ty::Bound(..)` and `ty::Infer(TyVar | FreshTy | FreshIntTy | FreshFloatTy)`. The try_as_dyn candidate (reflection mode) expects a concrete self type; a bound var or unresolved inference variable should not reach it. Hitting this arm is a solver-invariant violation.
Source
Thrown at compiler/rustc_next_trait_solver/src/solve/trait_goals.rs:911
// FIXME(try_as_dyn): check what kind of projections we can allow
ExistentialPredicate::Projection(_) => return Err(NoSolution.into()),
// Auto traits do not affect lifetimes outside of specialization,
// which is disabled in reflection.
ExistentialPredicate::AutoTrait(_) => {}
}
}
ecx.add_goal(
GoalSource::Misc,
goal.with(cx, ty::OutlivesPredicate(ty_lifetime, lifetime)),
)?;
ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}
ty::Bound(..)
| ty::Infer(
ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_),
) => {
panic!("unexpected type `{self_ty:?}`")
}
_ => Err(NoSolution.into()),
}
})
}
fn consider_builtin_field_candidate(
ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
if goal.predicate.polarity != ty::PredicatePolarity::Positive {
return Err(NoSolution.into());
}
if let ty::Adt(def, args) = goal.predicate.self_ty().kind()
&& let Some(FieldInfo { base, ty, .. }) =
def.field_representing_type_info(ecx.cx(), args)
&& {View on GitHub (pinned to 22057b88b0)
Solutions
- Report at https://github.com/rust-lang/rust/issues with `{self_ty:?}` from the panic.
- Drop `-Znext-solver=reflection` / `-Znext-solver`.
- Annotate the self type so it resolves before the candidate.
- `rustup update nightly`.
Example fix
// before — self type unknown in a try_as_dyn context under reflection let x = reflect_thing(); // returns inferred type // after — annotate the concrete type let x: Concrete = reflect_thing::<Concrete>();
Defensive patterns
Strategy: validation
Validate before calling
// The solver found an unexpected self-type in a trait goal.
// Common cause: the Self type of a bound is a closure, generator, or
// other inferred type that the solver cannot normalise.
// Validate by naming the Self type explicitly.
trait Marker {}
// BAD: let f = || (); impl Marker for typeof(f) {} (impossible to name)
// GOOD: struct NamedFn; impl Marker for NamedFn {}
struct NamedFn;
impl Marker for NamedFn {}
fn use_marker<T: Marker>() { use_marker::<NamedFn>(); } Type guard
// Never put unnameable types (closures, async blocks, generators) as the
// Self type of a trait impl. Replace them with a named struct/enum:
struct Handler;
impl Trait for Handler { /* ... */ }
// If you need closure semantics, store the closure in a field of a named type. Prevention
- Never implement traits directly on closures, async blocks, or other compiler-generated types — wrap them in a named struct.
- Provide an explicit `Self` type in trait goals via turbofish rather than letting inference pick an anonymous type.
- When a bound fails with this ICE, replace the inferred self type with a named type and re-test.
When it happens
Trigger: A `try_as_dyn` trait goal whose self type is a `Bound` var or unbound `TyVar`/`Fresh*` reaches the builtin candidate under `-Znext-solver` reflection mode.
Common situations: Nightly users running reflection mode (`-Znext-solver=reflection`) or the try-as-dyn experiment, where a generic/escaping-bound self type wasn't resolved before the candidate ran; typically after a rustc update.
Related errors
- try_as_dyn helper trait doesn't have assoc types
- unexpected self ty `{:?}` when normalizing `<T as Pointee>::
- unexpected self ty `{:?}` when normalizing `<T as Discrimina
- unexpected type `{ty:?}`
- unexpected infer {a_ty:?} {b_ty:?}
AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03).
Data as JSON: /data/errors/4c2679f5b7a380eb.json.
Report an issue: GitHub.