From 698f8c2f01ea549d77d7dc3338a12e04c11057b9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:02:58 +0200 Subject: Adding upstream version 1.64.0+dfsg1. Signed-off-by: Daniel Baumann --- .../rustc_error_codes/src/error_codes/E0373.md | 73 ++++++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 compiler/rustc_error_codes/src/error_codes/E0373.md (limited to 'compiler/rustc_error_codes/src/error_codes/E0373.md') diff --git a/compiler/rustc_error_codes/src/error_codes/E0373.md b/compiler/rustc_error_codes/src/error_codes/E0373.md new file mode 100644 index 000000000..effa597aa --- /dev/null +++ b/compiler/rustc_error_codes/src/error_codes/E0373.md @@ -0,0 +1,73 @@ +A captured variable in a closure may not live long enough. + +Erroneous code example: + +```compile_fail,E0373 +fn foo() -> Box u32> { + let x = 0u32; + Box::new(|y| x + y) +} +``` + +This error occurs when an attempt is made to use data captured by a closure, +when that data may no longer exist. It's most commonly seen when attempting to +return a closure as shown in the previous code example. + +Notice that `x` is stack-allocated by `foo()`. By default, Rust captures +closed-over data by reference. This means that once `foo()` returns, `x` no +longer exists. An attempt to access `x` within the closure would thus be +unsafe. + +Another situation where this might be encountered is when spawning threads: + +```compile_fail,E0373 +fn foo() { + let x = 0u32; + let y = 1u32; + + let thr = std::thread::spawn(|| { + x + y + }); +} +``` + +Since our new thread runs in parallel, the stack frame containing `x` and `y` +may well have disappeared by the time we try to use them. Even if we call +`thr.join()` within foo (which blocks until `thr` has completed, ensuring the +stack frame won't disappear), we will not succeed: the compiler cannot prove +that this behavior is safe, and so won't let us do it. + +The solution to this problem is usually to switch to using a `move` closure. +This approach moves (or copies, where possible) data into the closure, rather +than taking references to it. For example: + +``` +fn foo() -> Box u32> { + let x = 0u32; + Box::new(move |y| x + y) +} +``` + +Now that the closure has its own copy of the data, there's no need to worry +about safety. + +This error may also be encountered while using `async` blocks: + +```compile_fail,E0373,edition2018 +use std::future::Future; + +async fn f() { + let v = vec![1, 2, 3i32]; + spawn(async { //~ ERROR E0373 + println!("{:?}", v) + }); +} + +fn spawn(future: F) { + unimplemented!() +} +``` + +Similarly to closures, `async` blocks are not executed immediately and may +capture closed-over data by reference. For more information, see +https://rust-lang.github.io/async-book/03_async_await/01_chapter.html. -- cgit v1.2.3