Unexpected repeated mutable borrow duration

Hi, I'm quite new to Rust, and I'm having trouble working out how to solve an error relating to a second mutable borrow of *self. I've attempted to trim down the code I have to replicate the error, and I've put it up in a playground here.

The error that the compiler produces makes some sense to me -- I think the borrow checker believes that the mutable borrow of self.src could last longer than the execution of the read function even if the early return statement is not hit. What I'm not sure about is how to go about persuading it that it doesn't!

error[E0499]: cannot borrow `*self` as mutable more than once at a time
  --> src/main.rs:36:9
   |
27 |     fn read(&mut self, len: usize) -> &[u8]
   |             - let's call the lifetime of this reference `'1`
28 |     {
29 |         let b = self.src.fill();
   |                 -------- first mutable borrow occurs here
30 |         if b.len() >= len {
31 |             return &b[..len];
   |                    --------- returning this value requires that `self.src` is borrowed for `'1`
...
36 |         self.expensive_op();
   |         ^^^^ second mutable borrow occurs here

For context, in the non-minimised implementation, the Source type is actually something from an external library implementing BufRead, so I can't (easily) modify the internals of that. Thing::expensive_op() is basically a function that will concatenate multiple buffers from BufRead's fill_buf through a memory copying operation to ensure that we actually have enough bytes from the source to successfully decode a frame from the input.

Does it work if you return &self.src.fill()[..len] instead? (assuming that makes sense to do)

I just tried this, and it does (playground link)! So this has me a bit confused now... why does that work and not the original version? They seem the same to me!

To return a reference from the function, the reference's lifetime must extend beyond the function, so the fill call must borrow src until after the function returns.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.