|
12 | 12 |
|
13 | 13 | register_long_diagnostics! {
|
14 | 14 |
|
| 15 | +E0373: r##" |
| 16 | +This error occurs when an attempt is made to use data captured by a closure, |
| 17 | +when that data may no longer exist. It's most commonly seen when attempting to |
| 18 | +return a closure: |
| 19 | +
|
| 20 | +``` |
| 21 | +fn foo() -> Box<Fn(u32) -> u32> { |
| 22 | + let x = 0u32; |
| 23 | + Box::new(|y| x + y) |
| 24 | +} |
| 25 | +``` |
| 26 | +
|
| 27 | +Notice that `x` is stack-allocated by `foo()`. By default, Rust captures |
| 28 | +closed-over data by reference. This means that once `foo()` returns, `x` no |
| 29 | +longer exists. An attempt to access `x` within the closure would thus be unsafe. |
| 30 | +
|
| 31 | +Another situation where this might be encountered is when spawning threads: |
| 32 | +
|
| 33 | +``` |
| 34 | +fn foo() { |
| 35 | + let x = 0u32; |
| 36 | + let y = 1u32; |
| 37 | +
|
| 38 | + let thr = std::thread::spawn(|| { |
| 39 | + x + y |
| 40 | + }); |
| 41 | +} |
| 42 | +``` |
| 43 | +
|
| 44 | +Since our new thread runs in parallel, the stack frame containing `x` and `y` |
| 45 | +may well have disappeared by the time we try to use them. Even if we call |
| 46 | +`thr.join()` within foo (which blocks until `thr` has completed, ensuring the |
| 47 | +stack frame won't disappear), we will not succeed: the compiler cannot prove |
| 48 | +that this behaviour is safe, and so won't let us do it. |
| 49 | +
|
| 50 | +The solution to this problem is usually to switch to using a `move` closure. |
| 51 | +This approach moves (or copies, where possible) data into the closure, rather |
| 52 | +than taking references to it. For example: |
| 53 | +
|
| 54 | +``` |
| 55 | +fn foo() -> Box<Fn(u32) -> u32> { |
| 56 | + let x = 0u32; |
| 57 | + Box::new(move |y| x + y) |
| 58 | +} |
| 59 | +``` |
| 60 | +
|
| 61 | +Now that the closure has its own copy of the data, there's no need to worry |
| 62 | +about safety. |
| 63 | +"##, |
| 64 | + |
15 | 65 | E0381: r##"
|
16 | 66 | It is not allowed to use or capture an uninitialized variable. For example:
|
17 | 67 |
|
|
28 | 78 | }
|
29 | 79 |
|
30 | 80 | register_diagnostics! {
|
31 |
| - E0373, // closure may outlive current fn, but it borrows {}, which is owned by current fn |
32 | 81 | E0382, // use of partially/collaterally moved value
|
33 | 82 | E0383, // partial reinitialization of uninitialized structure
|
34 | 83 | E0384, // reassignment of immutable variable
|
|
0 commit comments