Help me to translate this basic pattern to Rust. The Rust compiler complains about ownership; it cannot pass the self
reference to the close
method because immutable references to self.files
are still alive.
I'm confused because HashMap::get
is compete and it's not an iterator, so what is the problem in changing the files
object?
use std::collections::HashMap;
struct File {
ino: u64
}
struct Filesystem {
files: HashMap<u64, File>
}
impl File {
fn close(&self, fs: &mut Filesystem) {
fs.files.remove(&self.ino);
}
}
impl Filesystem {
fn release(&mut self, ino: u64) {
let file = self.files.get(&ino);
if file.is_some() {
file.unwrap().close(self)
}
}
}
fn main() {
let mut fs = Filesystem { files: HashMap::new() };
fs.release(1)
}
The compiler error is
error: cannot borrow `*self` as mutable because `self.files` is also borrowed as immutable [E0502]
file.unwrap().close(self)
^~~~
note: immutable borrow occurs here
let file = self.files.get(&ino);
^~~~~~~~~~
note: immutable borrow ends here
}
^
help: run `rustc --explain E0502` to see a detailed explanation
I ended up with pointers; it's comprehensible and fast. I don't see the advantages of RefCell
because the error will be encountered at runtime anyway, so it's the same segfault with a different message.
use std::collections::HashMap;
struct File {
ino: u64
}
struct Filesystem {
files: HashMap<u64, File>
}
impl File {
fn close(&self, fs: *mut Filesystem) {
unsafe { (*fs).files.remove(&self.ino); }
}
}
impl Filesystem {
fn release(&mut self, ino: u64) {
let p = self as *mut Filesystem;
let file = self.files.get(&ino);
if file.is_some() {
file.unwrap().close(p)
}
}
}
fn main() {
let mut fs = Filesystem { files: HashMap::new() };
fs.release(1)
}