Change:
fake_reads: Default::default(), }; <ins> let _ = euv::ExprUseVisitor::new( &FnCtxt::new(self, self.tcx.param_env(closure_def_id), closure_def_id), &mut delegate, ) .consume_body(body); // There are several curious situations with coroutine-closures where // analysis is too aggressive with borrows when the coroutine-closure is // marked `move`. Specifically: // // 1. If the coroutine-closure was inferred to be `FnOnce` during signature // inference, then it's still possible that we try to borrow upvars from // the coroutine-closure because they are not used by the coroutine body // in a way that forces a move. See the test: // `async-await/async-closures/force-move-due-to-inferred-kind.rs`. // // 2. If the coroutine-closure is forced to be `FnOnce` due to the way it // uses its upvars, but not *all* upvars would force the closure to `FnOnce`. // See the test: `async-await/async-closures/force-move-due-to-actually-fnonce.rs`. // // This would lead to an impossible to satisfy situation, since `AsyncFnOnce` // coroutine bodies can't borrow from their parent closure. To fix this, // we force the inner coroutine to also be `move`. This only matters for // coroutine-closures that are `move` since otherwise they themselves will // be borrowing from the outer environment, so there's no self-borrows occuring. // // One *important* note is that we do a call to `process_collected_capture_information` // to eagerly test whether the coroutine would end up `FnOnce`, but we do this // *before* capturing all the closure args by-value below, since that would always // cause the analysis to return `FnOnce`. if let UpvarArgs::Coroutine(..) = args && let hir::CoroutineKind::Desugared(_, hir::CoroutineSource::Closure) = self.tcx.coroutine_kind(closure_def_id).expect("coroutine should have kind") && let parent_hir_id = self.tcx.local_def_id_to_hir_id(self.tcx.local_parent(closure_def_id)) && let parent_ty = self.node_ty(parent_hir_id) && let hir::CaptureBy::Value { move_kw } = self.tcx.hir_node(parent_hir_id).expect_closure().capture_clause { // (1.) Closure signature inference forced this closure to `FnOnce`. if let Some(ty::ClosureKind::FnOnce) = self.closure_kind(parent_ty) { capture_clause = hir::CaptureBy::Value { move_kw }; } // (2.) The way that the closure uses its upvars means it's `FnOnce`. else if let (_, ty::ClosureKind::FnOnce, _) = self .process_collected_capture_information( capture_clause, &delegate.capture_information, ) { capture_clause = hir::CaptureBy::Value { move_kw }; } } </ins> // As noted in `lower_coroutine_body_with_moved_arguments`, we default the capture mode // to `ByRef` for the `async {}` block internal to async fns/closure. This means // that we would *not* be moving all of the parameters into the async block by default.

Discussion:
Rustc panicked when I attempted to use async in poll. I wanted to compose an async task inside my custom future :
I believe this is a duplicate of , which I have a local branch to fix but which needs a bit of cleanup first.

<!-- Thank you for filing a regression report! A regression is something that changed between versions of Rust but was not supposed to. Please provide a short summary of the regression, along with any information you feel is relevant to replicate it. --I tried this code (minimized): I expected to see this happen: Compiles Instead, this happened (): Instead, this happened (latest nightly): ICE Related: Mentioning :wink: Best guess: <details<summaryBacktrace</summary<p</p</details<!-- If you know when this regression occurred, please add a line like below, replacing with one of stable, beta, or nightly. -- modify labels: +regression-from-nightly-to-nightly -regression-untriaged Thanks for investigating! -
Nightly-only features aren't typically regression triaged. I'll look into it soon.