Не может заимствовать как неизменяемый, поскольку он также заимствован как изменяемый в аргументах функции

Что здесь происходит ( детская площадка )?

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 --> :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 не оценивает все функциональные параметры перед оценкой вызова функции следующего уровня?

Эта строка:

 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 --> :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 не делает такого анализа управления streamом.

Это было впервые создано как ошибка # 6268 , теперь она интегрирована в RFC 811 .

Начиная с 1.25.0-ночного 2018-01-13, можно использовать несексные времена жизни . Если вы запустите свой пример в ночном режиме Rust и включите шлюз функций NLL, используя #![feature(nll)] , он теперь будет компилироваться без ошибок .

  • Разрешены ли полиморфные переменные?
  • Как инициализировать поля структуры, которые ссылаются друг на друга
  • Почему не рекомендуется принимать ссылку на String (& String), Vec (& Vec) или Box (& Box) в качестве аргумента функции?
  • Почему я не могу сохранить значение и ссылку на это значение в одной и той же структуре?
  • Какое время жизни я использую для создания структур Rust, которые циклически ссылаются друг на друга?
  • Как передать непересекающиеся fragmentы из вектора в разные streamи?
  • Печатает! заимствовать или владеть переменной?
  • Как происходит конфликтная реализация `From` при использовании родового типа?
  • Что означает «размер не реализовано»?
  • Можно ли сделать тип только подвижным и не копируемым?
  • Измените вариант enums при перемещении поля в новый вариант
  • Давайте будем гением компьютера.