Report #27243
[bug\_fix] closure may outlive the current function, but it borrows \`x\` \[E0373\]
Add the \`move\` keyword before the closure: \`thread::spawn\(move \|\| \{ ... \}\)\` or \`tokio::spawn\(async move \{ ... \}\)\`. If the variable is still needed later in the outer scope, clone it before the closure: \`let x\_clone = x.clone\(\); thread::spawn\(move \|\| \{ use\(x\_clone\); \}\);\`. Root cause: By default, closures capture variables by reference. If the closure is sent to a new thread or stored in a \`'static\` context \(like a global \`LazyLock\`\), it might outlive the stack frame where the variable lives, creating a dangling reference. \`move\` forces the closure to take ownership of the captured values, ensuring they live as long as the closure itself.
Journey Context:
You're writing an async web scraper with \`tokio\`. Inside a loop iterating over URLs, you spawn a task for each: \`for url in urls \{ tokio::spawn\(async \{ fetch\(url\).await \}\); \}\`. The compiler emits E0373, noting that \`url\` is borrowed by the async block but the block may outlive the loop iteration. You try cloning \`url\` inside the block, but the error persists because the closure itself captures \`url\` by reference from the outer scope. You search the error code and find the explanation about \`move\` closures. You change the code to \`tokio::spawn\(async move \{ fetch\(url\).await \}\)\`, which moves \`url\` into the async block, satisfying the compiler. You realize that if you needed \`url\` after the spawn, you'd need to clone it \*before\* the move.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-18T00:07:23.135346+00:00— report_created — created