{"id":"921d7d0cce73839e","repo":"rust-lang/rust","slug":"use-of-await-outside-of-an-async-context","errorCode":null,"errorMessage":"use of `await` outside of an async context.","messagePattern":"use of `await` outside of an async context\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compiler/rustc_ast_lowering/src/expr.rs","lineNumber":1032,"sourceCode":"        // this name to identify what is being awaited by a suspended async functions.\n        let awaitee_ident = Ident::with_dummy_span(sym::__awaitee);\n        let (awaitee_pat, awaitee_pat_hid) =\n            self.pat_ident_binding_mode(gen_future_span, awaitee_ident, hir::BindingMode::MUT);\n\n        let task_context_ident = Ident::with_dummy_span(sym::_task_context);\n\n        // unsafe {\n        //     ::std::future::Future::poll(\n        //         ::std::pin::Pin::new_unchecked(&mut __awaitee),\n        //         ::std::future::get_context(task_context),\n        //     )\n        // }\n        let poll_expr = {\n            let awaitee = self.expr_ident(span, awaitee_ident, awaitee_pat_hid);\n            let ref_mut_awaitee = self.expr_mut_addr_of(span, awaitee);\n\n            let Some(task_context_hid) = self.task_context else {\n                unreachable!(\"use of `await` outside of an async context.\");\n            };\n\n            let task_context = self.expr_ident_mut(span, task_context_ident, task_context_hid);\n\n            let new_unchecked = self.expr_call_lang_item_fn_mut(\n                span,\n                hir::LangItem::PinNewUnchecked,\n                arena_vec![self; ref_mut_awaitee],\n            );\n            let get_context = self.expr_call_lang_item_fn_mut(\n                gen_future_span,\n                hir::LangItem::GetContext,\n                arena_vec![self; task_context],\n            );\n            let call = match await_kind {\n                FutureKind::Future => self.expr_call_lang_item_fn(\n                    span,\n                    hir::LangItem::FuturePoll,","sourceCodeStart":1014,"sourceCodeEnd":1050,"githubUrl":"https://github.com/rust-lang/rust/blob/22057b88b091743bc0fd8d592a9264f0a6951403/compiler/rustc_ast_lowering/src/expr.rs#L1014-L1050","documentation":"This `unreachable!` fires inside the `.await` desugaring helper when `self.task_context` is `None`, i.e. the lowering context has no enclosing async task context to pull a `task_context` binding from. By the time `.await` is being lowered, the parser/type-checker should already have emitted a clean user-facing error for `await` outside an async function/block/closure. Reaching this point means that gate was bypassed — an internal compiler bug.","triggerScenarios":"Triggered when `lower_await` (the `.await` desugaring at expr.rs:1031) is invoked but `self.task_context` was never set — there is no enclosing `async fn`, `async {}`, `async ||`, or other coroutine context that establishes a task-context binding. The `let Some(task_context_hid) = self.task_context else { unreachable!(...) }` arm fires.","commonSituations":"In principle user-facing: writing `.await` in a non-async function should produce a graceful E0728-style diagnostic long before lowering. This `unreachable!` is the backstop for when the earlier check is missing (a rustc regression). It can also be hit by procedural-macro-injected `.await` nodes into sync contexts, or by nightly features (`gen` blocks, async-fn-in-traits edge cases) where the context-tracking logic has a hole.","solutions":["As a user who sees the ICE: report it with the reproducer to https://github.com/rust-lang/rust/issues.","Move the `.await` into an `async fn`/`async {}` block — if the earlier diagnostic fires instead, the bug is elsewhere.","If a proc-macro is injecting await expressions, ensure they only land inside async contexts.","If developing rustc: confirm the parser/sema check that rejects `.await` outside async (the `allow_await` feature-gate path) ran before lowering, and that `task_context` is set whenever the function enters an async scope."],"exampleFix":"// before — .await outside async context (should be caught earlier, but bypassed)\nfn run() -> u8 { fut.await }\n\n// after — wrap in an async context\nasync fn run() -> u8 { fut.await }","handlingStrategy":"validation","validationCode":"// `.await` is only legal inside an async context. Validate the enclosing\n// item is async BEFORE writing the await, or wrap the call in an async block.\n//\n// Good: async fn fetch() { req.await; }\n// Bad:  fn fetch()  { req.await; } // ICE/error: await outside async\n//\n// Pre-commit guard (catch it at source, not at lowering):\n//   rg -n '\\.await' --type rust | rg -v 'async (fn|move|\\{)'\n//\n// If you must call async code from sync code, spawn an executor:\n//   let r = tokio::runtime::Runtime::new()?.block_on(async { req.await });","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Only use `.await` inside `async fn`, `async {}`, or `async move {}`","If a sync caller needs async results, bridge via a runtime's `block_on`","Enable clippy::await_holding_lock / async-aware lints to surface context mistakes early","Add a pre-commit grep for `.await` outside `async` items"],"tags":["rustc","ast-lowering","async","await","ice"],"analyzedSha":"22057b88b091743bc0fd8d592a9264f0a6951403","analyzedAt":"2026-08-03T08:09:25.915Z","schemaVersion":2}