rust-lang/rust · critical
no such associated type in `AsyncFn*`: {:?}
Error message
no such associated type in `AsyncFn*`: {:?} What it means
This panic lives in consider_builtin_async_fn_trait_candidates (normalizes_to.rs:627). That function computes the projection for an async-callable trait by matching the projection's def_id against exactly three lang items: CallOnceFuture, CallRefFuture, and AsyncFnOnceOutput. The else branch fires only if the def_id is an async-fn-family projection that the compiler recognizes but this match does not handle. It is an internal invariant: under correct compiler logic every async-fn projection goal is one of those three, so reaching the else means a new async-closure/projection lang item was introduced elsewhere without updating this arm.
Source
Thrown at compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs:627
[
I::GenericArg::from(goal.predicate.self_ty()),
tupled_inputs_ty.into(),
env_region.into(),
],
),
output_coroutine_ty.into(),
)
} else if cx.is_projection_lang_item(def_id, SolverProjectionLangItem::AsyncFnOnceOutput) {
(
ty::AliasTerm::new(
cx,
goal.predicate.alias.kind,
[goal.predicate.self_ty(), tupled_inputs_ty],
),
coroutine_return_ty.into(),
)
} else {
panic!("no such associated type in `AsyncFn*`: {:?}", def_id)
};
let pred = ty::ProjectionPredicate { projection_term, term }.upcast(cx);
Self::probe_and_consider_implied_clause(
ecx,
CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
goal,
pred,
[goal.with(cx, output_is_sized_pred)]
.into_iter()
.chain(nested_preds.into_iter().map(|pred| goal.with(cx, pred)))
.map(|goal| (GoalSource::ImplWhereBound, goal)),
)
}
fn consider_builtin_async_fn_kind_helper_candidate(
ecx: &mut EvalCtxt<'_, D>,
goal: Goal<I, Self>,View on GitHub (pinned to 22057b88b0)
Solutions
- Update to the latest nightly toolchain (rustup update nightly); async-closure/next-solver mismatches are usually fixed within days.
- Disable the next solver for the affected crate: remove -Znext-solver (or pass -Znext-solver=no) from RUSTFLAGS / .cargo/config.toml so the projection is handled by the legacy solver.
- Reduce the failing crate to a minimal reproducer and file an ICE at https://github.com/rust-lang/rust/issues including the nightly hash and the def_id printed in the panic.
- If you depend on a crate using nightly async-closure features, pin that crate to a version compatible with your toolchain, or pin your toolchain to a known-good nightly.
Example fix
# before (RUSTFLAGS in .cargo/config.toml) [build] rustflags = ["-Znext-solver"] # after [build] rustflags = []
Defensive patterns
Strategy: type-guard
Validate before calling
// Before projecting an associated type off an async fn trait,
// confirm the trait + variant expose that name. Only these exist:
// AsyncFn::Output, AsyncFnMut::Output, AsyncFnOnce::Output,
// AsyncFnOnce::CallOnceOutput
fn assert_async_fn_output<F>()
where
F: for<'a> AsyncFn<&'a str>, // concrete AsyncFn* bound
F::Output: Send, // only valid associated name
{}
Type guard
// Narrow an async-callable to a known variant before projecting Output.
trait AsyncFnRet { type Output; }
impl<F: AsyncFn<T>, T> AsyncFnRet for F { type Output = <Self as AsyncFn<T>>::Output; }
fn is_async_fn_with_output<F: AsyncFnRet>() where F::Output: Sized {}
Prevention
- Never invent associated-type names on AsyncFn/AsyncFnMut/AsyncFnOnce; only Output (and CallOnceOutput on AsyncFnOnce) exist.
- Use higher-ranked bounds (`for<'a> AsyncFn<&'a str>`) rather than projecting from an unbounded `F: AsyncFn<...>`.
- Pin your nightly toolchain: this ICE is a rustc_next_trait_solver bug, behavior shifts between nightlies.
- If it reproduces on stable, file a rustc issue with the minimal trait-solver repro before changing library code.
When it happens
Trigger: Reached only when a NormalizesTo goal for an AsyncFn*-family projection lands in consider_builtin_async_fn_trait_candidates whose def_id is none of CallOnceFuture / CallRefFuture / AsyncFnOnceOutput. Concretely: compiling code that exercises async closures / async-fn-trait projections under -Znext-solver on a nightly where the lang-item table and this match arm have drifted out of sync (e.g. mid-development of the CoroutineClosure / async-closure feature).
Common situations: Using unstable async-closure or AsyncFn features on a bleeding-edge nightly with -Znext-solver enabled; a rustc toolchain regression where a recently-added async projection lang item is not yet wired into this match; bisecting across nightlies during an async-fn-trait refactor in rustc itself.
Related errors
- `Tuple` does not have an associated type: {:?}
- `FusedIterator` does not have an associated type: {:?}
- unexpected associated item `{:?}` for `{self_ty:?}`
- `Unsize` does not have an associated type: {:?}
- `Destruct` does not have an associated type: {:?}
AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03).
Data as JSON: /data/errors/f291b278c81c278c.json.
Report an issue: GitHub.