You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
structMyStruct{name:String,}pubfnmain(){letmut s = MyStruct{name:String::from(""),};let _h = std::thread::spawn(move || {
s.name = String::from("hello");// line 10println!("{: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:
This is working as intended. In editions 2021 and later, the closure captures only the s.name field. Furthermore, since you annotated the closure with move, the closure moves the s.name field out into the closure. This leaves s to be a struct with a temporarily uninitialized field, which is fine.
Your line 11 doesn't run in my testing. This is because the programs ends before the spawned thread gets a turn to executed.
Your code is roughly equivalent to the following, which doesn't have UB:
structClosure{captured_name:String,}implClosure{fnmy_call(mutself){self.captured_name = String::from("hello");println!("{:p} {:?}",&self.captured_name,self.captured_name);}}structMyStruct{name:String,}fnmy_spawn(f:Closure){// stuff here that calls f.my_call()}pubfnmain(){letmut s = MyStruct{name:String::from(""),};let _h = my_spawn(Closure{captured_name: s.name});
s.name = String::from("world");println!("{:p} {:?}",&s.name, s.name);}
I tried this code (playground):
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:
Uncomment the line 13:
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)
The text was updated successfully, but these errors were encountered: