What's the most idiomatic way to deal with partial borrows/borrow splitting?

70 points philogy 84 comments

I'm continuously running into this problem when writing Rust and it's seriously making me want to quit. I have some large struct with lots of related data that I want to group in a data structure for convenience with different methods that do different things, however because the borrow checker doesn't understand partial borrows across function boundaries I keep getting errors for code like this:

struct Data {
    stuff: Vec<u32>,
    queue: Vec<u32>,
}

impl Data {
    fn process(&mut self, num: u32) {
        self.queue.push(num);
    }

    fn process_all(&mut self) {
        for &num in &self.stuff {
            // Error: cannot borrow `self` because I already borrowed `.stuff`
            self.process(num);
        }
    }
}

Do you just say "f*ck structs" and pass everything member? Do you manually split members on a case by case basis as needed? How do you deal with this effectively?

I've been writing Rust for various things for over 2 years now but this is making me seriously consider abandoning the language. I feel very frustrated, structs are meant to be the fundamental unit of abstraction and the way of grouping data. I just want to "do the thing".

It seems I either have to compromise on performance, using intermediary Vecs to accumulate and pass around values or just split things up as needed.