use std::fs::File;
use std::io::Read;
pub struct Foo {
maybe_file: Option<File>,
}
impl Foo {
pub fn init(&mut self) {
self.maybe_file = Some(File::open("/proc/uptime").unwrap());
}
pub fn print(&mut self) {
let mut file = self.maybe_file.unwrap();
let mut s = String::new();
file.read_to_string(&mut s).unwrap();
println!("Uptime: {}", s);
}
}
fn main() {}
Compiling this will give me:
error[E0507]: cannot move out of borrowed content
--> src/main.rs:14:24
|
14 | let mut file = self.maybe_file.unwrap();
| ^^^^ cannot move out of borrowed content
Why is this happening? What do I do to solve it?
self
has type&mut Foo
inprint
, that is, it is a borrowed mutable reference to a value of typeFoo
. Types in Rust move ownership by default, that is, taking something by-value will statically invalidate the source and stop the programmer from using it again (unless it is reinitialized). In this case,unwrap
has the signature:That is, it is taking the
Option
value by-value and thus trying to consume ownership of it. Hence,self.maybe_file.unwrap()
is trying to consume the data inmaybe_file
which would leaveself
pointing to partially invalid data (it is illegal to use themaybe_file
field after that). There's no way the compiler can enforce this with borrowed references which have to be valid always as they could point anywhere, so it is illegal to move out.Fortunately, one can avoid this problem: the
as_ref
method creates anOption<&T>
out of an&Option<T>
and theas_mut
method creates anOption<&mut T>
out of an&mut Option<T>
. The resultingOption
is then no longer behind a reference and so it is legal to consume it viaunwrap
:This differs slightly because
file
has type&mut File
instead ofFile
, but fortunately&mut File
is all that is necessary for the rest of the code.Another approach to making this work is using manual pattern matching:
This is doing exactly the same thing as the
.as_mut().unwrap()
just more explicitly: theref mut
is create a reference pointing directly into the memory occupied byself.maybe_file
, just likeas_mut
.