rust-lang/rust · error
coroutine lowered from async fn should be in fn
Error message
coroutine lowered from async fn should be in fn
What it means
region_name.rs:841: when naming a region for an async-fn coroutine with CoroutineSource::Fn, the diagnostic looks up the parent item and calls parent_item.fn_decl().expect("coroutine lowered from async fn should be in fn"). The invariant: a coroutine desugared from an `async fn` is always nested inside an fn item, so the parent must have a fn_decl.
Source
Thrown at compiler/rustc_borrowck/src/diagnostics/region_name.rs:841
)) => " of async block",
hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
hir::CoroutineDesugaring::Async,
hir::CoroutineSource::Closure,
))
| hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Async) => {
" of async closure"
}
hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
hir::CoroutineDesugaring::Async,
hir::CoroutineSource::Fn,
)) => {
let parent_item =
tcx.hir_node_by_def_id(tcx.hir_get_parent_item(mir_hir_id).def_id);
let output = &parent_item
.fn_decl()
.expect("coroutine lowered from async fn should be in fn")
.output;
span = output.span();
if let hir::FnRetTy::Return(ret) = output {
hir_ty = Some(self.get_future_inner_return_ty(ret));
}
" of async function"
}
hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
hir::CoroutineDesugaring::Gen,
hir::CoroutineSource::Block,
)) => " of gen block",
hir::ClosureKind::Coroutine(hir::CoroutineKind::Desugared(
hir::CoroutineDesugaring::Gen,
hir::CoroutineSource::Closure,
))
| hir::ClosureKind::CoroutineClosure(hir::CoroutineDesugaring::Gen) => {View on GitHub (pinned to 7088e4b63a)
Solutions
- File a rustc ICE with the minimized async fn lifetime error.
- Restructure the async fn (move the problematic borrow out, name the lifetime explicitly) so the region-naming heuristic is not reached.
- Bisect across nightlies with cargo bisect-rustc.
- Try the equivalent non-async code to confirm the async-specific lowering path.
Defensive patterns
Strategy: fallback
Prevention
- Treat as a borrowck diagnostic ICE; report with the minimized async-fn lifetime error.
- Name lifetimes explicitly and move problematic borrows out of the async fn to avoid region-naming heuristics.
- Bisect with cargo bisect-rustc and compare stable vs nightly.
- Pin to a known-good nightly for async-heavy code.
When it happens
Trigger: Region-naming for a borrowck error inside an async fn where the parent item is not an fn (has no fn_decl), an inconsistency in coroutine lowering or HIR parent tracking.
Common situations: A borrowck diagnostic ICE triggered by lifetime errors inside async fn on a nightly with a coroutine-lowering regression.
Related errors
- coroutine lowered from gen fn should be in fn
- `async gen` closures not supported yet
- immutable unnamed local
- return depth from strip_n_refs should be smaller than the in
- coroutine lowered from async gen fn should be in fn
AI-assisted analysis of rust-lang/rust@7088e4b63a (2026-08-10).
Data as JSON: /api/errors/9bebdd32fd83deff.
Report an issue: GitHub.