#Borrow Misunderstanding, cannot borrow `*self` as mutable because it is also borrowed as immutable

18 messages · Page 1 of 1 (latest)

tiny marten
#

Here's my code, the error is in the code.

struct BorrowMisunderstanding{
    vector: Vec<i32>,
    third_value: i32
}

impl BorrowMisunderstanding{

    pub fn stuff(&mut self) -> &mut Self{
        //                              v <====== immutable borrow occurs here
        for (i, number) in self.vector.iter().enumerate(){
            if i == 3{
                // cannot borrow `*self` as mutable because it is also borrowed as immutable
                self.inner_stuff(number);
                //self.third_value = *number; // I can do that no big of a deal
                return self;
            }
        }
        self
    }
    fn inner_stuff(&mut self, number: &i32){
        // do stuff but in another function instead of doing a billion and a half thing in one
        self.third_value = *number;
    }
}```
I welcome any suggestion to try another design, I did it the way I would do in javascript or C. Suppose I should do it more functionally? I have no idea how.
Thank you
#

I could use into_iter with an intermediate variable with a cloned value.
But that sounds bad to me

cosmic mirage
#

so there are a few issues here, but the most important one is: the way you've structured your code, number is a reference into the vector field, while the &mut self reference is a reference that covers both vector and third_value. if you were able to call inner_stuff like that, you would have two references to the same data, one of which is mutable, and rust fundamentally does not allow you to have multiple references to the same place where one is mutable. there is no way to get a function call like self.function_that_takes_mut(&self.field) to compile

strange fulcrum
#

Is there a reason you're taking a &i32 and not a i32 ?

tiny marten
#

Yeah, so the only way to iterate and borrow what's in the vector is to clone the vector, or copy it

strange fulcrum
#

Do you need to mutate the vec? Or do you need to mutate just third_value?

strange fulcrum
cosmic mirage
#

there are a few ways you could restructure it. fundamentally you need to separate the two parts of the state.

one is to change who owns either vector or third_value, ie move one of the fields outside of BorrowMisunderstanding and pass it by reference to stuff

another is to split them out into separate structs like

struct BorrowMisunderstanding{
    vector: Vec<i32>,
    third_value: Value,
}

struct Value(i32);
impl Value {
    fn inner_stuff(&mut self, number: &i32) { /* .. */ }
}

this would allow you to call the method as self.third_value.inner_stuff(number) which only requires borrowing third_value instead of the entirety of self so there's no overlap

tiny marten
#

Oh, thank you

strange fulcrum
#
fn inner_stuff(third_value: &mut i32, number: i32) {
    *third_value = number;
}
cosmic mirage
#

and yeah a third would be to write it like

impl BorrowMisunderstanding {
    fn inner_stuff(third_value: &mut i32, number: &i32) {
        *third_value = *number;
    }
}

so you can call it like Self::inner_stuff(&mut self.third_value, number)

tiny marten
strange fulcrum
tiny marten
cosmic mirage
#

fundamentally your problem is that you're trying to borrow the entirety of self while you already have a reference to one of its fields, and these are various ways to make sure you can partially borrow only the fields needed by the method you're calling, instead of all fields

tiny marten
#

I'm so used to other programming languages which tends to agglomerate a lot of data into one big object