Cannot borrow error leaving me confused


#1

I’m struggling with the borrow checker. I have a piece of code like this:

fn start_parser<F,R:BufRead>(reader:&mut Reader<R>,
                             buf:&mut Vec<u8>,
                             ns_buf:&mut Vec<u8>,
                             level:&str, mut callback: F)
    where F: FnMut(&mut Reader<R>,&mut Vec<u8>, &mut Vec<u8>, &mut BytesStart)

{
    loop{
        let mut nse = reader.read_namespaced_event(buf, ns_buf);
        match nse {
            Ok((ref ns, Event::Start(ref mut e))) => {
                match *ns {
                    Some(b"http://www.w3.org/2002/07/owl#") =>
                    {
                        callback(reader, buf, ns_buf, e);
                    }
                    Some(_) =>{
                        println!("{}: Unknown Element:{:?}",
                                 level, e.local_name())
                    }
                    None => {
                        println!("{}: Unknown Element without ns:{:?}",
                                 level, e.local_name());
                    }
                }
            }
            Err(e) => {
                println!("Error: {}", e);
            },
            Ok((_, Event::Eof)) => break,
            _ => {
                // Ignore non starts
            }
        }
    }
}

which complains because I am borrowing twice.

error[E0499]: cannot borrow `*buf` as mutable more than once at a time
  --> io_quick_port.rs:43:42
   |
37 |         let mut nse = reader.read_namespaced_event(buf, ns_buf);
   |                                                    --- first mutable borrow occurs here
...
43 |                         callback(reader, buf, ns_buf, e);
   |                                          ^^^ second mutable borrow occurs here
...
63 |     }
   |     - first borrow ends here

I guessed that I can see the cause of the error, although I am not
sure how to fix it. So I tried a minimal reproduction. The best I can
come up with is this:

fn main() {
    let mut v:Vec<usize> = vec![];

    f1(&mut v);

}

fn f1(v:&mut Vec<usize>){
    f2(v);
    f3(v);
}

fn f2(v:&mut Vec<usize>){
    println!("{}",v.len());
}

fn f3(v:&mut Vec<usize>){
    println!("{}",v.len());
}

This seems to be of similar form to me: f1 gets a mutable reference to
a vector, then passes it mutable to f2 and f3. But now rust seems
entirely happy.

My code is trying to use quick_xml to build a parser that recurses
down a tree. My thought was to hand the Vector buffers that it
requires around. Perhaps I need to create lots of new ones.


#2

The reason for the error is the nse is holding a reference (or has a lifetime param) to something borrowed from buf - at least as far as the compiler is concerned. While nse is live, you cannot borrow buf again.

Can you show more of the relevant code here?


#3

Here’s a stripped down version of the same problem: https://play.rust-lang.org/?gist=b0ed7d669584f2e7e5dd9ecd0c84a567&version=stable

fn main() {
    let mut v: Vec<usize> = vec![];

    f1(&mut v);
}

fn borrow(v: &mut Vec<usize>) -> Option<&mut Vec<usize>> {
    Some(v)
}

fn f1(v: &mut Vec<usize>) {
    match borrow(v) {
        Some(_x) => f2(v),
        None => {}
    }
}

fn f2(v: &mut Vec<usize>) {
    println!("{}", v.len());
}

You could use _x there to call f2 - that essentially transfers the unique borrow of v back to that match arm. But you cannot use v itself until the match statement is finished.

Back to your situation. What exactly would the callback do? Continue using the reader and the buffers to parse more of the payload? You can try to arrange it such that a callback takes ownership of the state (reader + bufs), rather than borrowing, and then passes them back once it’s done. Alternatively, they can borrow it but they’d need to get access to the buf from within the Event::Start payload, if that’s even possible, since it now has the unique borrow of the buf. Another approach is the callback examines just the state that’s not borrowed by the event and instead returns some indicator of what the outer loop should do to proceed. Finally, another approach is to use the bytes crate and pass owned buffers around (internally they’re refcounted views into an underlying buffer) by cloning them. I’m not familiar with quick_xml so some of the above (maybe all) doesn’t make sense/work.


#4

Yes, @vitalyd you are right. It is the signature of read_namespaced_event
that is causing the issue. Here is my version of the minimal reproduction.

fn main() {
    let mut v:Vec<usize> = vec![];

    f1(&mut v);

}

fn f1(v:&mut Vec<usize>){
    let _s = f2(v);
    f3(v);
}

fn f2<'a>(v:&'a mut Vec<usize>)
          -> Option<&'a mut Vec<usize>>
{
    Some(v)
}

fn f3(v:&mut Vec<usize>){
    println!("{}",v.len());
}

And I guess that is correct, since in this destructing, e has the
same lifetime as nse. So I may well be passing an event and a vector
to which is has reference.

Ok((ref ns, Event::Start(ref mut e)))

Which means that I have to create new ones I fear. Still, it makes my
code easier. I was passing these vectors around like a mad thing.