Не может заимствовать как неизменяемый, потому что он также заимствован как изменяемый в аргументах функции
Что здесь происходит ( детская площадка)?
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);
}
Для меня они выглядят абсолютно эквивалентно - я имею в виду, я ожидаю, что первое будет преобразовано во второе во время компиляции. Разве Rust не оценивает все параметры функции перед оценкой вызова функции следующего уровня?
1 ответ
Эта строка:
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 не выполняет такого рода анализ потока управления.
Это было сначала создано как ошибка # 6268, теперь это интегрировано в RFC 811.
Начиная с 1.25.0-nightly 2018-01-13, можно использовать нелексические времена жизни. Если вы запустили свой пример на ночной Rust и включили функцию NLL gate, используя #![feature(nll)]
, теперь он будет компилироваться без ошибок.