Изменяемый заем в аргументе функции - PullRequest
1 голос
/ 14 марта 2020

Почему следующий код не компилируется ( детская площадка ):

use std::collections::HashMap;

fn main() {
    let mut h: HashMap<u32, u32> = HashMap::new();
    h.insert(0, 0);
    h.insert(1, h.remove(&0).unwrap());
}

Контролер заимствований жалуется, что:

error[E0499]: cannot borrow `h` as mutable more than once at a time

Код безопасен, однако, и почти механическое преобразование последней строки приводит к компиляции ( детская площадка ):

    //h.insert(1, h.remove(&0).unwrap());
    let x = h.remove(&0).unwrap();
    h.insert(1, x);

Насколько я понимаю, этот вид проблемы был решен с нелексическими временами жизни. Этот вопрос является примером, и есть много других.

Есть ли какая-то хитрость, которая делает первый вариант неверным в конце концов, поэтому Руст прав, отказавшись от него? Или функция NLL все еще не завершена во всех случаях?

1 Ответ

0 голосов
/ 15 марта 2020

Компилятор Rust сначала оценивает вызывающий объект, а затем переданные ему аргументы. Вот почему он сначала занимает h.insert, а затем h.remove. Поскольку h уже заимствовано для insert, он запрещает второй заем для remove.

Эта ситуация не изменяется при использовании Polonius, средства проверки заимствования следующего поколения. Вы можете попробовать это сами с ночным компилятором:
RUSTFLAGS=-Zpolonius cargo +nightly run

Порядок оценки аналогичен в C ++: https://riptutorial.com/cplusplus/example/19369/evaluation-order-of-function-arguments

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...