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

  1. Report at https://github.com/rust-lang/rust/issues with `{self_ty:?}` from the panic.
  2. Drop `-Znext-solver=reflection` / `-Znext-solver`.
  3. Annotate the self type so it resolves before the candidate.
  4. `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

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


AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03). Data as JSON: /data/errors/4c2679f5b7a380eb.json. Report an issue: GitHub.