Struct used by ref in threads gets moved, compilation fails

I have a struct with data and a calculator over it. The calculator doesn't keep refs to the main struct, but the ref to it must be passed in calls. This makes it not compile.

I don't want to bother with Arcs for this, because the struct should be mutable (with Arc it becomes a big pain).

Playground

use std::{error::Error, thread};

struct Main { data: usize }
impl Main {
    fn calc(&self) -> Calc {
        Calc { data: self.data * 2 }
    }
}

struct Calc { pub data: usize }
impl Calc {
    fn do_calc(&mut self, param: usize, extra_data: &Main) -> Result<usize, Box<dyn Error>> {
        self.data += param;
        Ok(self.data)
    }
}

fn main() {
    let m = Main { data: 123 };
    thread::scope(|s| {
		for i in 0..5 {
			let mut calc = m.calc();
			
			s.spawn(move || {
                for j in 0..5 {
                    calc.do_calc(j, &m).unwrap();
                    println!("thread {i} {}", calc.data);
                }
            });
        }
    });
}

Error:

error[E0382]: borrow of moved value: `m`
  --> src/main.rs:27:19
   |
27 |             let mut calc = m.calc();
   |                            ^ value borrowed here after move
28 |             
29 |             s.spawn(move || {
   |                     ------- value moved into closure here, in previous iteration of loop
   |
   = note: move occurs because `m` has type `Main`, which does not implement the `Copy` trait

You can do this to move a reference into the inner closure, rather than move the struct itself:

		    let m = &m;

Playground

1 Like

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.