Reputation: 21727
use std::thread;
fn test2() {
let x = "abc".to_string();
thread::spawn(|| {
foo2(x);
});
}
fn foo2(x: String) {}
fn test1() {
let x = 1;
thread::spawn(|| {
foo1(x);
});
}
fn foo1(x: i32) {}
fn main() {}
The error:
error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function
--> <anon>:12:19
|
12 | thread::spawn(|| { foo1(x); });
| ^^ - `x` is borrowed here
| |
| may outlive borrowed value `x`
|
help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword, as shown:
| thread::spawn(move || { foo1(x); });
Why does the closure in test1
not take ownership of x
, which is specified by the signature (x: i32
) of foo1
? (I know I can add move
to make it work.) I guess it is due to that x
is copyable, but if it is copied into the closure then why do I still have the lifetime problem?
However test2
works.
Upvotes: 3
Views: 970
Reputation: 59015
Because it doesn't have to take ownership. Moving is more destructive than simply borrowing, so if the compiler thinks it can get away with not moving a captured value, it won't. It moves the String
because it has no other option. It borrows the i32
because it's Copy
.
But it can't get away with not borrowing it!
Aah, but the compiler doesn't know that until after it's decided if it's borrowing or moving a captured value. The heuristic it uses is just that: not always correct.
Couldn't it just work it out properly?
Probably, but no one's taught it how.
Upvotes: 4