这里发生了什么(playground)?
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);
}
给出了这个错误:
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
但是,如果您只是将代码更改为此,则可以正常工作:
fn main() {
let mut n = Number{ num: 0 };
let tmp = n.get() + 1;
n.set(tmp);
}
对我来说,那些看起来完全相同 - 我的意思是,我希望前者在编译期间转换为后者。在评估下一级向上函数调用之前,不会对所有函数参数进行评估吗?
答案 0 :(得分:21)
这一行:
n.set(n.get() + 1);
被贬低为
Number::set(&mut n, n.get() + 1);
现在可能会更清楚错误消息:
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
当Rust评估从左到右的参数时,该代码等同于:
let arg1 = &mut n;
let arg2 = n.get() + 1;
Number::set(arg1, arg2);
现在应该明白什么是错的。交换前两行,解决了这个问题,但Rust没有进行那种控制流分析。
这是首次创建为bug #6268,现在已集成到RFC 2094,non-lexical-lifetimes。如果您使用Rust 2018,则会自动启用NLL并your code will now compile without an error。