Closed
Description
I tried this code (playground):
struct MyStruct {
name: String,
}
pub fn main() {
let mut s = MyStruct {
name: String::from(""),
};
let _h = std::thread::spawn(move || {
s.name = String::from("hello"); // line 10
println!("{:p} {:?}", &s.name, s.name); // line 11
});
// let _ = _h.join().unwrap(); // line 13
// println!("{:p}", &s.name); // error[E0382]: borrow of moved value: `s.name`
s.name = String::from("world");
println!("{:p} {:?}", &s.name, s.name); // line 16
}
I expected to see this happen:
Cannot be compiled. String doesn't implement Copy trait so the s.name should be point to the same address at line 11 and line 16. This can cause concurrently reading & writing on s.name by (1) partially write s.name at line 10 (e.g. only write the ptr field); (2) read at line 16.
Instead, this happened:
Output:
0x7fff673b1ed0 "world"
Uncomment the line 13:
0x744cf7eaba20 "hello"
0x7fff38051b40 "world"
It seems that implicitly Copy happened to s or s.name, but it's illegal because nether String nor MyStruct implement the Copy trait.
Meta
Could be reproduced in the following versions with debug or release build:
Stable version: 1.86.0
Beta version: 1.87.0-beta.5
(2025-04-19 386abeb)
Nightly version: 1.88.0-nightly
(2025-04-25 b4c8b0c)
Metadata
Metadata
Assignees
Labels
No labels