0

I'm building a little Rust application used to make some statistics about programs and projects. My initial goal was to make it generic, so it can be modified and used as a library.

To do that I've created a Processor structure:

pub struct Processor {
    handles: Vec<Box<dyn FileTypeHandle>>,
    files_types: HashMap<String, Box<dyn FileType>>,
    bytes_count: usize,
    files_count: usize,
    dirs_count: usize,
}

What I've named handle is an implementation of FileTypeHandle trait that checks, from the extension of a file, if it can handle it. If it can, the file is processed by it and statistics are made.

Secondly, file_types are implementations of FileType trait that implement methods to write final statistics in console.

Let's assume that my handles vector is filled with some handles.

First, I needed to implement a function in the Processor to search in handles vector for one that can handle the ext file extension:

pub fn handle_ext(&mut self, ext: &String) -> Option<&Box<dyn FileTypeHandle>> {
    self.handles
        .iter()
        .find(move |handle: &&Box<dyn FileTypeHandle>| handle.can_handle(ext))
}

FileTypeHandle::can_handle is defined as:

fn can_handle(&self, ext: &String) -> bool;

I'm using the next function to get a file type in the processor, or create a default one:

pub fn get_file_type(&mut self, ext: &String) -> Option<&Box<dyn FileType>> {
    if !self.files_types.contains_key(ext) {
        let base = FileTypeBase::new(String::clone(ext));

        if let Some(v) = self.handle_ext(ext) {
            self.files_types.insert(String::clone(ext), v.handle(base));
        }
    }

    self.files_types.get(ext)
}

I think you understand what I expect from this code, but:

error[E0499]: cannot borrow `self.files_types` as mutable more than once at a time
  --> src\processor.rs:61:17
   |
59 |             if let Some(v) = self.handle_ext(ext) {
   |                              ---- first mutable borrow occurs here
60 | 
61 |                 self.files_types.insert(String::clone(ext), v.handle(base));
   |                 ^^^^^^^^^^^^^^^^                            - first borrow later used here
   |                 |
   |                 second mutable borrow occurs here

I've read lot of Rust documentation including the official book, but I didn't know why the static compilation check fails.

Okay, line 61 uses the self.file_types as said in the error message, but why is it the second borrow?! The first underlined word on line 59 is just self (or self.handle_ext?) which are not borrowing self.file_types.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Mindstorm38
  • 25
  • 1
  • 8
  • It's hard to answer your question because it doesn't include a [MRE]. We can't tell what crates (and their versions), types, traits, fields, etc. are present in the code. It would make it easier for us to help you if you try to reproduce your error on the [Rust Playground](https://play.rust-lang.org) if possible, otherwise in a brand new Cargo project, then [edit] your question to include the additional info. There are [Rust-specific MRE tips](//stackoverflow.com/tags/rust/info) you can use to reduce your original code for posting here. Thanks! – Shepmaster Oct 21 '19 at 17:35
  • 1
    Thanks for your reply (I did not know these tips for Rust questions ...), I will try to reproduce that on Rust Playground but my project is so specific that I don't know how to reproduce this... – Mindstorm38 Oct 21 '19 at 17:38
  • 1
    Your project may be specific, the the problem is not. It's going to be a duplicate of [one or more of hundreds of previous questions](https://www.google.com/search?q=site:stackoverflow.com%20rust%20borrow%20self%20mutable%20time), but we can't tell which until the code you've given reproduces the problem. – Shepmaster Oct 21 '19 at 17:41
  • 1
    Specifically, your problem is likely solved by [How to lookup from and insert into a HashMap efficiently?](https://stackoverflow.com/q/28512394/155423) and the reasoning is explained in [Returning a reference from a HashMap or Vec causes a borrow to last beyond the scope it's in?](https://stackoverflow.com/q/38023871/155423). – Shepmaster Oct 21 '19 at 17:43
  • @Shepmaster Thank you for your reply ! Very interesting. – Mindstorm38 Oct 21 '19 at 18:37

0 Answers0