Почему повторное заимствование работает только с указателями без ссылок? - PullRequest
0 голосов
/ 25 июня 2018

Этот вопрос и код адаптированы из Почему работает изменяемая ссылка на разыменованную изменяемую ссылку? . Ответы там объяснили повторное заимствование, но не причины для соглашений вокруг этого.

Два вызова test ниже кажутся эквивалентными, почему работает только первый?

fn main() {
    let mut string = String::new();
    let ref_string = &mut string;

    // Compiles
    test(&mut *ref_string);

    // Doesn't compile
    test(&mut string);
}

fn test(s: &mut String) {
    s.push('t');
}

1 Ответ

0 голосов
/ 25 июня 2018

Вам разрешено иметь только одну изменяемую ссылку на значение за раз.Когда вы изменчиво перезагружаетесь в качестве аргумента, компилятору будет тривиально видеть, что вы не собираетесь использовать ref_string одновременно, и, следовательно, код безопасен.

Мой мысленный образ таков, что для изменчивости есть «цепь опеки».ref_string является держателем и может временно отдать его до временного значения, созданного &mut *ref_string.Когда это выходит за рамки, изменчивость возвращается к нему.Это как если бы код был:

{
    let x = &mut *ref_string;
    test(x);
}

Однако, когда вы пытаетесь «обойти» и получить изменяемую ссылку, вы игнорируете цепочку опеки.Компилятор останавливает вас, потому что он не может тривиально увидеть, что это безопасно.


Следует отметить, что нелексические времена жизни улучшают исходную ситуацию.Когда включена проверка заимствования на основе MIR, компилятор может видеть, что ref_string больше не используется к тому времени, когда происходит второй вызов test, поэтому безопасно передавать туда эксклюзивный доступ.

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