1

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)
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Daniil Iaitskov
  • 5,525
  • 8
  • 39
  • 49
  • See also http://stackoverflow.com/q/32044301/155423, http://stackoverflow.com/q/28385339/155423, http://stackoverflow.com/q/36936221/155423. – Shepmaster Aug 14 '16 at 16:43
  • I didn't get the answer from the link. I don't have callbacks nor lambdas. – Daniil Iaitskov Aug 14 '16 at 17:01
  • None of the **3** links I provided (or the question that this is marked as a duplicate of) give you the answer? – Shepmaster Aug 14 '16 at 17:04
  • I feel like pointers are about the worst choice out of [the possible ones on the linked duplicate](http://stackoverflow.com/questions/30681468/passing-mutable-self-reference-to-method-of-owned-object), but it *is* valid. It's really a shame because you don't need `unsafe` code whatsoever. – Shepmaster Aug 14 '16 at 21:52

0 Answers0