rust-lang/rust · critical
expected free alias, found {kind:?}
Error message
expected free alias, found {kind:?} What it means
`normalize_free_alias` (free_alias.rs) normalizes top-level type aliases and const aliases gated behind `checked_type_aliases` / `type_alias_impl_trait`. Its match handles `AliasTermKind::FreeTy` and `FreeConst`; the `kind => panic!("expected free alias, found {kind:?}")` arm (line 54) fires when `free_alias.kind` is something else (Projection, Inherent, Opaque, Weak). The dispatcher is supposed to send only free aliases here, so a non-free kind means the projection-term dispatch routed the wrong alias category — a compiler bug.
Source
Thrown at compiler/rustc_next_trait_solver/src/solve/project_goals/free_alias.rs:54
let free = cx.type_of(def_id.into()).instantiate(cx, free_alias.args);
let free = self.normalize(GoalSource::Misc, goal.param_env, free)?;
free.into()
}
ty::AliasTermKind::FreeConst { def_id } if cx.is_type_const(def_id.into()) => {
let free = cx.const_of_item(def_id.into()).instantiate(cx, free_alias.args);
let free = self.normalize(GoalSource::Misc, goal.param_env, free)?;
free.into()
}
ty::AliasTermKind::FreeConst { .. } => {
return self.evaluate_const_and_instantiate_projection_term(
goal.param_env,
free_alias,
goal.predicate.term,
free_alias.expect_ct(),
);
}
kind => panic!("expected free alias, found {kind:?}"),
};
self.push_const_arg_has_type_goal(goal.param_env, goal.predicate.projection_term, actual)?;
self.eq(goal.param_env, goal.predicate.term, actual)?;
self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
}
}
View on GitHub (pinned to 22057b88b0)
Solutions
- Report at https://github.com/rust-lang/rust/issues with the `{kind:?}` value from the panic and a minimal type-alias repro.
- Disable `-Znext-solver` and the `checked_type_aliases` / `type_alias_impl_trait` features.
- `rustup update nightly`.
- Simplify the alias (split nested aliases, avoid alias-to-alias chains) to dodge the broken dispatch.
Example fix
// before — nested free alias that confuses dispatch type A = impl Iterator<Item = u8>; type B = A; // alias-to-alias chain // after — flatten to a single alias type B = impl Iterator<Item = u8>;
Defensive patterns
Strategy: validation
Validate before calling
// The solver expected a *free* alias (an alias of an associated type or opaque
// type that is not further constrained) but found a different `kind`.
// Validate that every alias used in trait goals is a fully-resolvable
// associated-type alias or opaque type alias.
trait Assoc { type A; }
impl Assoc for () { type A = i32; }
// GOOD: <() as Assoc>::A (free alias, normalises to i32)
fn ensure_alias_free<T: Assoc<A = i32>>() {} // constraint resolves alias Type guard
// Reject alias kinds that are not associated-type or opaque aliases.
// In practice this means: don't pass generic-parameter aliases or
// placeholder aliases into solver goals directly.
// Type-level check via a marker:
trait IsFreeAlias {}
impl<T> IsFreeAlias for T where T: /* assoc-type alias constraint */ {} Prevention
- Ensure every associated-type alias in scope is bound to a concrete definition (impl) or constrained before the solver inspects it.
- Avoid leaving alias types ambiguous across crate boundaries; add explicit `where` bounds.
- If using generic aliases, resolve them to concrete types before feeding into trait goals.
When it happens
Trigger: A projection term whose `AliasTermKind` is not `FreeTy`/`FreeConst` is handed to `normalize_free_alias`, typically because the dispatcher keyed off the wrong alias kind under `-Znext-solver` with `checked_type_aliases` or `type_alias_impl_trait` enabled.
Common situations: Nightly users of `#![feature(checked_type_aliases)]` or `#![feature(type_alias_impl_trait)]` under the next solver, often after mixing alias kinds (e.g. an opaque/weak alias mistaken for a free one) or after a rustc update to alias dispatch.
Related errors
- we never retry stalled queries if the parent was erased
- this never happens at the root, we're never in erased mode h
- unexpected orig_value: {ty:?}
- unexpected orig_value: {ct:?}
- ConstEquate should not be emitted when `-Znext-solver` is ac
AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03).
Data as JSON: /data/errors/3ed9d48c1769458a.json.
Report an issue: GitHub.