Borrow checker problem with multithread

I hve the following codes:

struct MyStruct<'a>(pub &'a i32);

impl<'a> MyStruct<'a> {
    pub fn func(&self) {}
}

fn thread_func<'a>(data: &Arc<Mutex<MyStruct<'a>>>) {
    let data = Arc::clone(data);
    thread::spawn(move || {
        data.lock().unwrap().func();
    });
}

It has this compiler error:

error[E0521]: borrowed data escapes outside of function
   --> src\trade\rabbit.rs:113:5
    |
111 |   fn thread_func<'a>(data: &Arc<Mutex<MyStruct<'a>>>) {
    |                  --  ---- `data` is a reference that is only valid in the function body
    |                  |
    |                  lifetime `'a` defined here
112 |       let data = Arc::clone(data);
113 | /     thread::spawn(move || {
114 | |         data.lock().unwrap().func();
115 | |     });
    | |      ^
    | |      |
    | |______`data` escapes the function body here
    |        argument requires that `'a` must outlive `'static`
    |
    = note: requirement occurs because of the type `std::sync::Mutex<trade::rabbit::MyStruct<'_>>`, which makes the generic argument `trade::rabbit::MyStruct<'_>` invariant
    = note: the struct `std::sync::Mutex<T>` is invariant over the parameter `T`
    = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance

This is the playground.
What is happening?

MyStruct is borrowing i32 for some limited lifetime, so it can't be moved (or shared) to the arbitrary-long-living thread.

1 Like

The thread spawned might outlive 'a.

Using Arc can keep owned data around as long as it is needed, but it cannot make references be valid longer than their lifetimes specify.

1 Like

If I need the Arc<MyStruct<'a>> to move between different threads, what should I do? Can channel or something solve that?

You have to ensure that all threads will terminate while the borrow in MyStruct is still alive, therefore you have to use scoped threads, not spawned ones.

3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.