Skip to content

Commit a160203

Browse files
committed
Rollup merge of rust-lang#27229 - AlisdairO:diagnostics371, r=Manishearth
As title! Part of rust-lang#24407. r? @Manishearth
2 parents a75c21f + 38c5af8 commit a160203

File tree

1 file changed

+50
-1
lines changed

1 file changed

+50
-1
lines changed

Diff for: src/librustc_borrowck/diagnostics.rs

+50-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,56 @@
1212

1313
register_long_diagnostics! {
1414

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+
1565
E0381: r##"
1666
It is not allowed to use or capture an uninitialized variable. For example:
1767
@@ -28,7 +78,6 @@ used.
2878
}
2979

3080
register_diagnostics! {
31-
E0373, // closure may outlive current fn, but it borrows {}, which is owned by current fn
3281
E0382, // use of partially/collaterally moved value
3382
E0383, // partial reinitialization of uninitialized structure
3483
E0384, // reassignment of immutable variable

0 commit comments

Comments
 (0)