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.