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

  1. Update to the latest nightly toolchain (rustup update nightly); async-closure/next-solver mismatches are usually fixed within days.
  2. 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.
  3. 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.
  4. 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

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


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