Why does the parameter “borrow” the value? [duplic

2019-02-20 14:06发布

问题:

This question already has an answer here:

  • Borrow checker and function arguments in Rust, correct or over zealous? [duplicate] 1 answer

Here is a sample:

struct X(u32);

impl X {
    fn f(&mut self, v: u32) {}
}

fn main() {
    let mut x = X(42);

    // works
    let v = x.0;
    x.f(v);

    // cannot use `x.0` because it was mutably borrowed
    x.f(x.0);
}

(Rust playground)

error[E0503]: cannot use `x.0` because it was mutably borrowed
  --> src/main.rs:16:9
   |
16 |     x.f(x.0);
   |     -   ^^^ use of borrowed `x`
   |     |
   |     borrow of `x` occurs here

What is the reason why x.f(x.0) does not work? x.0 is passed as an argument, bound to the v parameter, of type u32: there is absolutely no possibility that the function body access x.0 through the parameter.

Moreover, it seems very weird to me that:

f(something);

doesn't work, while:

v = something;
f(v);

works.

回答1:

When you do x.f(x.0), you have borrowed x to provide the &mut self to f before trying to borrow x again to get a reference to x.0. It is not possible to refer to x.0 twice at the same time. That is, the method f can't have both mutable access to x via &mut self (which includes x.0) and a seemingly immutable reference to x.0 at the same time.

When using a temporary variable, you actually get a copy of the value; this means you no longer refer to that int in X but 42. That's allowed.

Regarding the "non-lexical lifetimes" comments: Since f takes a good old u32 instead of a reference to it, x.f(x.0) should basically be equivalent to x.f(42), because the compiler can let go of x after getting the value out of x.0 and then mut-borrow x again to provide &mut self to f. However, the compiler determines the lifetimes and their requirements very early on during compilation; lifetimes are therefor currently broader than they have to be. rustc is currently unable to determine that the borrow on x due to the x.0 argument has ended before borrowing x for &mut self. There is work underway to fix this.