Получить изменяемую ссылку на неизменяемую переменную?

Aug 19 2020

Вот код, поскольку aон объявлен как неизменный, мы не можем получить изменяемую ссылку a, верно? Но этот скомпилирован, почему?

struct Foo;

fn main() {
    let a = &mut Foo;
    a.mut_ref();
}

impl Foo {
    fn mut_ref(&mut self) { }
}

кодовая ссылка

Ответы

5 SvenMarnach Aug 19 2020 at 14:07

Типа переменный aявляется &mut Foo, т.е. aсам по себе является изменяемой ссылкой на Fooобъект. Мутация aозначала бы указание на другой Fooобъект. Поскольку aсам по себе неизменяемый, вы не можете изменить то, на что aуказывает, и ваш код никоим образом не опровергает это.

Ваш код просто передает в &mut Fooкачестве selfпараметра mut_ref()- обратите внимание, что тип selfтакже &mut Foo. Автоматического разыменования не происходит - aуже есть именно тот тип, который используется для selfпараметра. Однако здесь мы запускаем неявный повторный заимствование , поэтому вызов эквивалентен Foo::mut_ref(&mut *a). Однако этот неявный повторный заимствование не является тем, что заставляет код работать - перемещение изменяемой ссылки aтакже было бы вполне допустимо.

Хотя aон неизменен как переменная, он по-прежнему является изменяемой ссылкой, поэтому вы можете изменить Fooобъект, на который он указывает (при условии, Fooчто какое-либо состояние изменилось). Вы не можете получить изменяемую ссылку a, которая должна иметь тип &mut &mut Foo.