Skip to content

Sample code with race condition introduced by thread::spawn can be compiled & run #140326

Closed
@zhongxinghong

Description

@zhongxinghong

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

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions