cannot move out of `*handle` which is behind a shared reference move occurs because `*handle` has type

Viewed 1359

I want to use foreach to wait for thread termination. However, the following error occurs and it is not realized. Please tell me.

cannot move out of `*handle` which is behind a shared reference  move occurs because `*handle` has type `std::thread::JoinHandle<()>`, which does not implement the `Copy` trait
let mut handles = Vec::new();
handles.push(thread::spawn(move || {
   let mut data = snd_rx.recv().unwrap();
   data += 1;
   let _ = rcv_tx.send(data);
}));

handles.iter().for_each(|handle| {
   let _ = handle.join(); // <- Error occurred
});

1 Answers

As already stated in a comment, the solution is to use into_iter instead of iter. Here's why:

When you call the .iter() method, you can iterate over the contents of handles and get a shared reference into the vector (that means, if handles is of type Vec<T>, the argument in the closure is of type &T). Therefore, you cannot modify the content of the vector.

But this is exactly what you are doing when assigning handle to _ (which just drops the assigned value immediately), since this assignment is moving the value out of the vector into the local variable. The error message is saying, that that would be okay, if JoinHandle was to implement Copy (like integers do for example, these values are not moved but copied on assignment), but it does not.

In contrast to that, when calling into_iter, you get an iterator, that consumes the vector (the vector moves into the iterator, which is then consumed when iterating over it). On every iteration, you get one element of the vector, but you also take ownership of that value, which is okay, since the vector is invalidated after iteration. As you now have ownership of handle, you can move it into _ and drop the value.

Related