不能借用为不可变的因为它在函数参数中也被借用为可变的

Tim*_*mmm 21 rust borrow-checker

这里发生了什么(游乐场)?

struct Number {
    num: i32
}

impl Number {
    fn set(&mut self, new_num: i32) {
        self.num = new_num;
    }
    fn get(&self) -> i32 {
        self.num
    }
}

fn main() {
    let mut n = Number{ num: 0 };
    n.set(n.get() + 1);
}
Run Code Online (Sandbox Code Playgroud)

给出了这个错误:

error[E0502]: cannot borrow `n` as immutable because it is also borrowed as mutable
  --> <anon>:17:11
   |
17 |     n.set(n.get() + 1);
   |     -     ^          - mutable borrow ends here
   |     |     |
   |     |     immutable borrow occurs here
   |     mutable borrow occurs here
Run Code Online (Sandbox Code Playgroud)

但是,如果您只是将代码更改为此,则可以:

fn main() {
    let mut n = Number{ num: 0 };
    let tmp = n.get() + 1;
    n.set(tmp);
}
Run Code Online (Sandbox Code Playgroud)

对我来说,那些看起来完全相同 - 我的意思是,我希望前者在编译期间转变为后者.Rust在评估下一级向上函数调用之前不评估所有函数参数吗?

wim*_*ica 21

这一行:

n.set(n.get() + 1);
Run Code Online (Sandbox Code Playgroud)

被贬低了

Number::set(&mut n, n.get() + 1);
Run Code Online (Sandbox Code Playgroud)

现在错误消息可能更清楚一些:

error[E0502]: cannot borrow `n` as immutable because it is also borrowed as mutable
  --> <anon>:18:25
   |
18 |     Number::set(&mut n, n.get() + 1);
   |                      -  ^          - mutable borrow ends here
   |                      |  |
   |                      |  immutable borrow occurs here
   |                      mutable borrow occurs here
Run Code Online (Sandbox Code Playgroud)

当Rust评估从左到右的参数时,该代码等同于:

let arg1 = &mut n;
let arg2 = n.get() + 1;
Number::set(arg1, arg2);
Run Code Online (Sandbox Code Playgroud)

现在应该明白什么是错的.交换前两行,修复了这一点,但Rust没有进行那种控制流分析.

这首先是作为bug#6268创建的,现在它被集成到RFC 2094中,非词汇生命周期.如果使用Rust 2018,则会自动启用NLL,现在您的代码将编译而不会出现错误.