rust-lang/rust · critical
reservation impl for trait with assoc item: {:?}
Error message
reservation impl for trait with assoc item: {:?} What it means
An `unimplemented!` in `consider_impl_candidate` (projection of an associated item through an impl) when the matched impl has polarity `Reservation` (`#[rustc_reservation_impl]`). Reservation impls are reserved for traits that have NO associated items; the solver does not know how to project an associated type/const through one, so it explicitly bails. Encountering it means a reservation impl was placed on a trait that declares an associated item — a configuration the new solver refuses to handle.
Source
Thrown at compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs:276
) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
let cx = ecx.cx();
let alias_def_id = goal.predicate.alias.expect_projection_def_id();
let goal_trait_ref = goal.predicate.alias.trait_ref(cx);
let impl_trait_ref = cx.impl_trait_ref(impl_def_id);
if !DeepRejectCtxt::relate_rigid_infer(ecx.cx()).args_may_unify(
goal.predicate.alias.trait_ref(cx).args,
impl_trait_ref.skip_binder().args,
) {
return Err(NoSolution.into());
}
// We have to ignore negative impls when projecting.
let impl_polarity = cx.impl_polarity(impl_def_id);
match impl_polarity {
ty::ImplPolarity::Negative => return Err(NoSolution.into()),
ty::ImplPolarity::Reservation => {
unimplemented!("reservation impl for trait with assoc item: {:?}", goal)
}
ty::ImplPolarity::Positive => {}
};
ecx.probe_trait_candidate(CandidateSource::Impl(impl_def_id)).enter(|ecx| {
let impl_args = ecx.fresh_args_for_item(impl_def_id.into());
let impl_trait_ref = impl_trait_ref.instantiate(cx, impl_args).skip_norm_wip();
ecx.eq(goal.param_env, goal_trait_ref, impl_trait_ref)?;
let where_clause_bounds = cx
.clauses_of(impl_def_id.into())
.iter_instantiated(cx, impl_args)
.map(Unnormalized::skip_norm_wip)
.map(|clause| goal.with(cx, clause));
ecx.add_goals(GoalSource::ImplWhereBound, where_clause_bounds)?;
// Bail if the nested goals don't hold here. This is to avoid unnecessarilyView on GitHub (pinned to 22057b88b0)
Solutions
- Remove the associated item from the trait, or remove the `#[rustc_reservation_impl]` attribute from the impl — the two are mutually exclusive for projection.
- If you are upstreaming a change to a std trait, consult the reservation-impl contract (the attribute exists to reserve a slot without providing the impl) before adding assoc items.
- Report as a rustc bug only if the trait genuinely has no associated items and the panic still fires (then it is a solver dispatch bug).
Example fix
// before — reservation impl on a trait WITH an associated item
#[rustc_reservation_impl]
impl Trait for () {}
trait Trait { type Item; }
// after — drop the reservation attribute, or drop the associated item
impl Trait for () { type Item = (); }
trait Trait { type Item; }
Defensive patterns
Strategy: validation
Validate before calling
// A reservation impl (#[rustc_reservation_impl]) is only legal on a
// marker/auto trait that has NO associated items. Verify before relying
// on one.
fn reservation_impl_legal(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool {
let assoc = tcx.associated_item_def_ids(trait_def_id);
assoc.is_empty()
} Type guard
// True only when the trait is a bare marker with no associated items,
// i.e. safe to attach a reservation impl to.
fn is_marker_trait_without_items(tcx: TyCtxt<'_>, did: DefId) -> bool {
tcx.associated_item_def_ids(did).is_empty() && tcx.is_auto_trait(did)
} Try / catch
use std::panic;
match panic::catch_unwind(panic::AssertUnwindSafe(|| solver.normalizes_to(goal))) {
Ok(v) => v,
Err(_) => Err("reservation impl requires a trait with no associated items"),
} Prevention
- Never place `#[rustc_reservation_impl]` on a trait that declares associated items.
- Treat reservation impls as reserved for pure marker/auto traits only.
- Audit downstream crates that introduce reservation impls against the trait's item list.
- If a trait gains an associated item, remove any pre-existing reservation impl.
When it happens
Trigger: A type has an `#[rustc_reservation_impl] impl Trait for ..` annotation AND `Trait` declares an associated type or associated const, and a `NormalizesTo` goal for that associated item is evaluated (e.g. `<T as Trait>::Item` is normalized). Only reachable on nightly/with the next solver since reservation impls are std-internal.
Common situations: Editing `core`/`std`/`alloc` internals where `#[rustc_reservation_impl]` is used (e.g. reserved impls for `Future`, auto traits). Almost never seen in third-party crates; if you see it, you are likely using the attribute incorrectly or added an associated item to a trait that still carries a reservation impl.
Related errors
- trait aliases do not have associated types: {:?}
- `Sized`/`MetaSized` does not have an associated type: {:?}
- `Copy`/`Clone` does not have an associated type: {:?}
- `FnPtr` does not have an associated type: {:?}
- `ConstKind::Param` should have been canonicalized to `Placeh
AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03).
Data as JSON: /data/errors/8fc190d57cbbddbc.json.
Report an issue: GitHub.