Why does borrow checker flag this?

I'm not trying to make some kind of design, just wondering why the borrow checker doesn't allow the below.

struct A {
    a: i32,
    b: i32,
}

fn m_borrow(int: &mut i32, a: &mut A){}

fn main() {
    let mut original = A{a: 5, b: 10};
    
    m_borrow(&mut original.b, &mut A{a: original.a, b: original.b});
}

It appears that in the code above, a.a is a primitive and therefore should be copied, same for a.b. I can rewrite the code below by extracting the second argument to my function, and the compiler will completely accept this:

let other = &mut A{a: original.a, b: original.b};

m_borrow(&mut original.b, other);

Currently borrowck just evaluates the arguments to a function in order most of the time (the one exception being two-phase borrows). Because the b field was borrowed first, it can't be accesssed until the borrow ends. It could in theory accept this in future if it did more complex analysis, involving changing the evaluation order if there are no side-effects involved, but I don't think there are any plans for that at the moment.

To add to the answer by @Kestrer, I'd expect this to work:

struct A {
    a: i32,
    b: i32,
}

fn m_borrow(int: &mut i32, a: &mut A){}

fn main() {
    let mut original = A{a: 5, b: 10};
    let another = A { a: original.a, b: original.b };
    
    m_borrow(&mut original.b, &mut another);
}

Yeah that appears to be the case. I tried switching the function arguments around and that was able to compile.

I can reproduce the error with this:

fn m_borrow(int: &mut i32, other: i32){}

fn main() {
    let mut num = 10;
    m_borrow(&mut num, num);
}

Just thought it was interesting to think about.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.