I have a question about this example that compiles without errors. It's confusing because intuitively, I'd expect there either to be a warning about a use after move when I trying to modify it in the second thread.
It seems like copies of cat.age is made implicitly.
On rust playground and locally, it compiles and outputs fine,
But on godbolt seems to correctly (at least to me) fail to compile with appropriate use after move errors. Compiler Explorer
use std::thread;
struct Cat {
name: String,
age: u32,
}
fn main() {
let mut cat = Cat {
name: "whiskers".to_string(),
age: 3,
};
let thread_1 = thread::spawn(move || {
cat.age += 1;
println!("The cat is {:?} years old in Thread 1", cat.age);
// not returning the cat here, but if I do i will get the desired compile error of move after use
});
thread_1.join().unwrap();
let thread_2 = thread::spawn(move || {
cat.age -= 1;
println!("The cat is {:?} years old in Thread 2", cat.age);
});
thread_2.join().unwrap();
println!("The cat is {:?} years old after threads", cat.age);
}
In this example the output is
The cat is 4 years old in Thread 1
The cat is 2 years old in Thread 2
The cat is 3 years old after threads
After realising that godbolt compiles with rustc
, I tried to compile it locally with rustc
as well, and to my surprise I get the appropriate errors this time. But not cargo
. Any reason why this behaviour is different?
❯ rustc src/main.rs
error[E0382]: use of moved value: `cat`
--> src/main.rs:22:34
|
9 | let mut cat = Cat {
| ------- move occurs because `cat` has type `Cat`, which does not implement the `Copy` trait
...
14 | let thread_1 = thread::spawn(move || {
| ------- value moved into closure here
15 | cat.age += 1;
| ------- variable moved due to use in closure
...
22 | let thread_2 = thread::spawn(move || {
| ^^^^^^^ value used here after move
...
error[E0382]: borrow of moved value: `cat`
--> src/main.rs:28:57
...
For more information about this error, try `rustc --explain E0382`.
vs
❯ cargo build
warning: field `name` is never read
--> src/main.rs:4:5
|
3 | struct Cat {
| --- field in this struct
4 | name: String,
| ^^^^
|
= note: `#[warn(dead_code)]` on by default
warning: `cat_age` (bin "cat_age") generated 1 warning
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.04s