0

Why can't I do this?

pub fn start_workers(&mut self) {
    // start all the worker threads
    self.dispatch_thread = Some(spawn(||{
        for _i in 1..10 {
            println!("Price = {}", 10);
            thread::sleep(time::Duration::from_secs(1));
        }
    }));
    self.dispatch_thread.unwrap().join();
}

I'm getting the following error,

error[E0507]: cannot move out of borrowed content
   --> src/orderbook.rs:195:9
    |
195 |         self.dispatch_thread.unwrap().join();
    |         ^^^^ cannot move out of borrowed content
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Danny
  • 391
  • 2
  • 12

1 Answers1

4

This is indeed a non-obvious error message. Have a look at the method signatures for unwrap:

pub fn unwrap(self) -> T

and take:

pub fn take(&mut self) -> Option<T>

unwrap consumes the Option (note the receiver is self), which would leave self.dispatch_thread in an unknown state. If you use take it is returned to the None state as you probably intended.

You probably want take in this context; as shown here:

use std::thread;
use std::time;

struct Foo {
    foo: Option<thread::JoinHandle<()>>,
}

impl Foo {
    fn nope(&mut self) {
        self.foo = Some(thread::spawn(|| {
            for _i in 1..10 {
                println!("Price = {}", 10);
                thread::sleep(time::Duration::from_millis(10));
            }
        }));
        self.foo.take().unwrap().join();
    }
}

fn main() {
    let foo = Some(thread::spawn(|| {
        for _i in 1..10 {
            println!("Price = {}", 10);
            thread::sleep(time::Duration::from_millis(10));
        }
    }));
    foo.unwrap().join();

    let mut foo = Foo { foo: None };
    foo.foo = Some(thread::spawn(|| {
        for _i in 1..10 {
            println!("Price = {}", 10);
            thread::sleep(time::Duration::from_millis(10));
        }
    }));
    foo.foo.unwrap().join();

    let mut foo = Foo { foo: None };
    foo.nope();
}

Note that assert!(foo.foo.is_none()); would be similarly illegal; but is valid in this case because we don't violate that constraint. In the method with &self as a receiver, this isn't true, which is why it is illegal in that case.

trent
  • 25,033
  • 7
  • 51
  • 90
Doug
  • 32,844
  • 38
  • 166
  • 222