How to work around multiple mutable borrow of *self?

#1

Hi, guys!

As to the following code, the compiler complains about multiple mutable borrows of self in method bar. The first mutable borrow occurs when the map field borrowed from self, and the second occurs when calling push method.

I know the compiler’s complains make sense. And I could work around by removing the push method and inline its body to the loop in bar. But what if it’s impractical to inline the method (for example, it’s too complicated and should be better to be packed in a method)? Any other work-arounds?

use std::collections::HashMap;

#[derive(Debug)]
struct Foo{
    map: HashMap<i32, i32>,
    vec: Vec<i32>, 
    i: i32
}

impl Foo {
    pub fn bar(&mut self) {
        let map = &mut self.map;
        for (_,item) in map.drain() {
            self.push(item)
        }
    }
    
    pub fn push(&mut self, item: i32) {
        self.vec.push(item)
    }
}

fn main() {

}
0 Likes

#2

If you’re using two distinct members of your struct there will be no error, e.g. like you said “inline” the push method

impl Foo {
    pub fn bar(&mut self) {
        let map = &mut self.map;
        for (_,item) in map.drain() {
            self.vec.push(item)
        }
    }
}

The problem is, that the compiler can’t decide wether you’re only accessing only field or all in your push method, because it takes &mut self as parameter.
If you’re usecase is more complicated and you can’t apply the fix so easily like here, please paste a better example :slight_smile:

2 Likes

#3

Another way to handle this is to pass your vec to push directly instead of self. This way Rust can reason that your codr is using disjoint fields of your type and you can extract some code into another function.

0 Likes