self is of type &mut Foo in print , that is, it is a borrowed mutable reference to a value of type Foo . Types in Rust become ownership by default, that is, taking something by value, the source is statically invalid and do not allow the programmer to use it again (unless it is reinitialized). In this case, unwrap has the signature:
impl Option<T> { fn unwrap(self) -> T { ...
That is, he takes the value of Option by value and, thus, tries to absorb his possession. Therefore, self.maybe_file.unwrap() tries to use the data in maybe_file , which will leave self , indicating partially invalid data (after that, maybe_file field cannot be used). It is impossible for the compiler to apply this with borrowed links, which should always be valid, since they can point anywhere, therefore it is illegal to move.
Fortunately, this problem can be avoided: the as_ref method creates Option<&T> from &Option<T> and as_mut creates Option<&mut T> from &mut Option<T> . The resulting Option then no longer behind the link, so it's legal to use it through unwrap :
let mut file = self.maybe_file.as_mut().unwrap();
This is slightly different because file is of type &mut File instead of file , but fortunately, &mut File is all that is needed for the rest of the code.
Another approach to doing this work is to use manual pattern matching:
match self.maybe_file { Some(ref mut file) => println!(...), None => panic!("error: file was missing") }
This does the same as .as_mut().unwrap() , more explicitly: ref mut creates a link pointing directly to the memory occupied by self.maybe_file , just like as_mut .