rust-lang/rust · error
`async gen` closures not supported yet
Error message
`async gen` closures not supported yet
What it means
An `unimplemented!("\`async gen\` closures not supported yet")` ICE in `rustc_hir_typeck`'s closure type-checker. The `CoroutineClosure` desugaring handles `Gen` (gen closures) and `Async` (async closures), but the `AsyncGen` combination (async-gen closures) is recognized but not yet implemented and panics at closure.rs:197.
Source
Thrown at compiler/rustc_hir_typeck/src/closure.rs:197
(
Ty::new_coroutine(tcx, expr_def_id.to_def_id(), coroutine_args.args),
Some(CoroutineTypes { resume_ty, yield_ty }),
)
}
hir::ClosureKind::CoroutineClosure(kind) => {
let (bound_return_ty, bound_yield_ty) = match kind {
hir::CoroutineDesugaring::Gen => {
// `iter!` closures always return unit and yield the `Iterator::Item` type
// that we have to infer.
(tcx.types.unit, self.infcx.next_ty_var(expr_span))
}
hir::CoroutineDesugaring::Async => {
// async closures always return the type ascribed after the `->` (if present),
// and yield `()`.
(bound_sig.skip_binder().output(), tcx.types.unit)
}
hir::CoroutineDesugaring::AsyncGen => {
unimplemented!("`async gen` closures not supported yet")
}
};
// Compute all of the variables that will be used to populate the coroutine.
let resume_ty = self.next_ty_var(expr_span);
let closure_kind_ty = match expected_kind {
Some(kind) => Ty::from_closure_kind(tcx, kind),
// Create a type variable (for now) to represent the closure kind.
// It will be unified during the upvar inference phase (`upvar.rs`)
None => self.next_ty_var(expr_span),
};
let coroutine_captures_by_ref_ty = self.next_ty_var(expr_span);
let closure_args = ty::CoroutineClosureArgs::new(
tcx,
ty::CoroutineClosureArgsParts {
parent_args,View on GitHub (pinned to 7088e4b63a)
Solutions
- Do not combine `async` and `gen` in the same closure; use a plain `async` block or a `gen` block separately.
- Express the pattern as an `async fn` returning a `gen` block (or vice-versa) instead of a single async-gen closure.
- Wait for / upgrade to a nightly where `AsyncGen` closures are implemented.
Example fix
// before (async gen closure -> ICE)
let c = async || { yield 1; };
// after — separate async and gen
async fn f() {
let _g = gen { yield 1; };
} Defensive patterns
Strategy: validation
Validate before calling
# Detect async+gen closure combinations rg -nE 'async \|\|.*yield|gen move \|\|.*await' src/ # review matches
Prevention
- Do not combine `async` and `gen` in one closure.
- Express async-over-gen as separate `async fn` + `gen` block.
- Track nightly support for `AsyncGen` closures before adopting.
When it happens
Trigger: Writing a closure that combines async and gen desugaring (an `async gen` closure) — e.g. an `async || { yield ... }` form — on a nightly toolchain where the coroutine-closure syntax is parsed but `AsyncGen` lowering is unfinished.
Common situations: Experimenting with the newest coroutine-closure features (`gen` + `async` combined) on nightly before the implementation lands. The parser accepts it; the type-checker does not.
Related errors
AI-assisted analysis of rust-lang/rust@7088e4b63a (2026-08-10).
Data as JSON: /api/errors/8c2c9793004e86d5.
Report an issue: GitHub.