rust-lang/rust · critical

AsyncIterator is not const

Error message

AsyncIterator is not const

What it means

Internal `unreachable!` panic in the next-gen trait solver's const-effect candidate assembly for the built-in `AsyncIterator` trait (`core::async_iter::AsyncIterator`). The method `consider_builtin_async_iterator_candidate` exists only to satisfy the `assembly::GoalKind` interface; `AsyncIterator` is explicitly non-const, so execution reaching here is a solver routing bug. The compiler ICEs instead of emitting a diagnostic.

Source

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

    fn consider_builtin_iterator_candidate(
        _ecx: &mut EvalCtxt<'_, D>,
        _goal: Goal<I, Self>,
    ) -> Result<Candidate<I>, NoSolutionOrRerunNonErased> {
        Err(NoSolutionOrRerunNonErased::NoSolution(NoSolution))
    }

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

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

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

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

    fn consider_builtin_destruct_candidate(
        ecx: &mut EvalCtxt<'_, D>,

View on GitHub (pinned to 22057b88b0)

Solutions

  1. Remove any `const`/`~const` bound on `AsyncIterator`; async iteration cannot run in const context.
  2. Confirm the goal isn't synthesized indirectly (e.g. via a `#[const_trait]` trait whose supertrait list includes `AsyncIterator`).
  3. Reproduce with `-Znext-solver=no` / classic solver to verify it is a next-solver-only ICE and report upstream with the reproducer.
  4. Track the rust nightly where it appeared and bisect — async-trait const routing changes frequently.

Example fix

// before
const fn drive<T: const AsyncIterator>(_: T) {}

// after
fn drive<T: AsyncIterator>(_: T) {}
Defensive patterns

Strategy: validation

Validate before calling

// build.rs: reject const bounds on AsyncIterator before the solver panics
fn main() {
    let src = std::fs::read_to_string("src/lib.rs").unwrap_or_default();
    for banned in ["~const AsyncIterator", "const AsyncIterator", "async gen"] {
        assert!(!src.contains(banned), "rejected: {banned} — AsyncIterator needs a runtime executor and is not const");
    }
    println!("cargo:rerun-if-changed=src/lib.rs");
}

Prevention

When it happens

Trigger: The solver attempts to compute a `HostEffectPredicate` goal for the `AsyncIterator` lang item — i.e. a bound `T: const AsyncIterator` / `T: ~const AsyncIterator`, or an async-generator type forced into const evaluation through generic constraints or `#[const_trait]` propagation.

Common situations: Mixing `async`/`AsyncIterator` with nightly `const_trait_impl` experiments; aliasing or projecting over an async iterator inside a `const fn`; enabling `-Znext-solver` on async-heavy code; nightly toolchain regression after the effect-goal routing was widened to cover more built-in traits.

Related errors


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