Как работает множественная изменяемая ссылочная профилактика в Rust? - PullRequest
0 голосов
/ 13 октября 2019

Почему разрешено делать что-то вроде этого:

fn main() {
    let mut w = MyStruct;
    w.fun1();
}

struct MyStruct;

impl MyStruct {
    fn fun1(&mut self) {
        self.fun2();
    }

    fn fun2(&mut self) {
        println!("Hello world 2");
    }
}

В приведенном выше коде fun1() получает mut MyStruct и вызывает fun2() также с mut MyStruct. Это двойная изменяемая ссылка в одной области видимости?

1 Ответ

1 голос
/ 24 октября 2019

Это разрешено, поскольку средство проверки заимствований может сделать вывод, что во время выполнения доступна только одна изменяемая ссылка. Пока fun2 выполняется, никакой другой оператор в fun1 не выполняется. Когда начинается выполнение следующего оператора в fun1 (если он был), fun2 уже отбросил свою изменяемую ссылку.

В другом связанном вопросе:

fn main() {
    let mut x1 = String::from("hello");
    let r1 = &mut x1;
    let r2 = &mut x1;

    r1.insert(0, 'w');
}

Мы можемскажем r2 никогда не используется, но заемщик решил, что это не должно быть разрешено. Рассмотрим этот пример:

fn main() {
    let mut x1 = String::from("hello");
    let r1 = &mut x1;
    r1.insert(0, 'w');

    let r2 = &mut x1;
    r2.insert(0, 'x');
}

Это компилируется и работает правильно. Я предполагаю, что средство проверки заимствования предполагает, что срок жизни r1 заканчивается до создания r2. Если это имеет смысл, вызов методов, изменяющих self, не должен вызывать удивления.

(я не знаю, почему 1-й фрагмент кода не компилируется, но я рад, что команда разработчиков ржавчины сделала так, чтопуть. r2 все равно не должно быть.)

...