Annotate function to allow mutable borrows of disjoint fields

impl<R: Read, H: Digest> BufRead for PackBufReader<R, H> {
    fn fill_buf(&mut self) -> io::Result<&[u8]> {
        self.inner.fill_buf()
    }

    fn consume(&mut self, amt: usize) {
        {
            //let buf = self.inner.fill_buf().unwrap(); // (1) This line works
            let buf = self.fill_buf().unwrap(); // (2) This does not work
            
            let len = std::cmp::min(amt, buf.len());
            self.hasher.process(&buf[0..len]);
        }

        self.consumed += amt;
        self.inner.consume(amt)
    }
}

Is there any way to annotate fill_buf() so that line (2) also works? (I assume line (1) works because rust can see that the fields are disjoint).

Compile log:

error[E0499]: cannot borrow `self.hasher` as mutable more than once at a time
   --> src/main.rs:126:13
    |
123 |             let buf = self.fill_buf().unwrap();
    |                       ---- first mutable borrow occurs here
...
126 |             self.hasher.process(&buf[0..len]);
    |             ^^^^^^^^^^^ second mutable borrow occurs here
127 |         }
    |         - first borrow ends here

error: aborting due to previous error
1 Like

Unfortunately there’s no way to annotate or otherwise make it work as written. As you say, the disjointness is “lost” when you call through the function taking &mut self. That said, there’s nothing wrong going through the fields to make the compiler see the disjointness. Alternatively, you can pass the fields as references to the helper functions for a similar effect.

2 Likes