rust-lang/rust · error

AsyncFn* are not yet const

Error message

AsyncFn* are not yet const

What it means

`consider_builtin_async_fn_trait_candidates` (effect_goals.rs:350) is `unimplemented!` because the built-in impls of the `AsyncFn`/`AsyncFnMut`/`AsyncFnOnce` family for closures and fn-like items have no const counterpart. The marker is 'not implemented yet' rather than 'impossible': async-fn-callability under `const` is an open design area (async in const is still incomplete).

Source

Thrown at compiler/rustc_next_trait_solver/src/solve/effect_goals.rs:350

        ))
        .to_host_effect_clause(cx, goal.predicate.constness);

        Self::probe_and_consider_implied_clause(
            ecx,
            CandidateSource::BuiltinImpl(BuiltinImplSource::Misc),
            goal,
            pred,
            requirements,
        )
        .map_err(Into::into)
    }

    fn consider_builtin_async_fn_trait_candidates(
        _ecx: &mut EvalCtxt<'_, D>,
        _goal: Goal<I, Self>,
        _kind: rustc_type_ir::ClosureKind,
    ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
        unimplemented!("AsyncFn* are not yet const")
    }

    fn consider_builtin_async_fn_kind_helper_candidate(
        _ecx: &mut EvalCtxt<'_, D>,
        _goal: Goal<I, Self>,
    ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
        unreachable!("AsyncFnKindHelper is not const")
    }

    fn consider_builtin_tuple_candidate(
        _ecx: &mut EvalCtxt<'_, D>,
        _goal: Goal<I, Self>,
    ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
        unreachable!("Tuple trait is not const")
    }

    fn consider_builtin_pointee_candidate(
        _ecx: &mut EvalCtxt<'_, D>,

View on GitHub (pinned to 22057b88b0)

Solutions

  1. Do not require async callables to satisfy a `const AsyncFn*` bound; refactor to avoid the obligation.
  2. Disable `const_async_blocks`/`host_effects` if the obligation is generated transitively rather than written by hand.
  3. Upgrade nightly and report the ICE with a minimal reproducer — async-in-const is under active development.
  4. Move the async code path out of the const context into a runtime function.

Example fix

// before: const async fn forced through a const AsyncFn obligation
const async fn fetch() -> u32 { 1 }
const fn drive<F: ~const AsyncFn() -> u32>(f: F) -> u32 { /* ... */ 0 } // ICE

// after: drop the ~const AsyncFn bound, call directly
const async fn fetch() -> u32 { 1 }
async fn drive() -> u32 { fetch().await }
Defensive patterns

Strategy: validation

Validate before calling

// AsyncFn* are not const. Reject async closures/blocks anywhere const eval may reach.
const fn reject_async_fn_in_const<F: AsyncFn>(_f: &F) {} // ICEs the next solver if hit

Prevention

When it happens

Trigger: Reached when the next solver evaluates a `T: const AsyncFn(..)` (or `AsyncFnMut`/`AsyncFnOnce`) host-effect goal and assembly reaches the async-fn built-in candidate branch (effect_goals.rs:345).

Common situations: Using `const async fn` or `async` blocks inside `const` context under `#![feature(const_async_blocks)]` combined with `const_trait_impl`; requiring a closure/async-fn to be `~const AsyncFn`.

Related errors


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