На границе API у вызывающего есть изменяемая ссылка, а функция принимает неизменяемую: как Rust допускает такую передачу, не перемещая исходную ссылку?
Rust выполняет неявное приведение &mut T к &T через временное совместное повторное заимствование. Исходная изменяемая ссылка не перемещается и обычно снова доступна после завершения вызова, если совместное заимствование больше не используется.
Модель заимствований Rust должна одновременно поддерживать безопасный общий доступ к данным и предотвращать конфликт между чтением и изменением. Поэтому изменяемую ссылку можно временно ослабить до неизменяемой, но обратное преобразование невозможно: наличие &T не доказывает право на эксклюзивное изменение значения.
Такой подход позволяет функциям принимать минимально необходимые права доступа. Функция, которой нужно только читать данные, объявляет параметр как &T, а вызывающий может передать ей как обычную, так и изменяемую ссылку.
&mut T не является типом, реализующим обычное копирование: одновременно существовать несколько изменяемых ссылок нельзя. Поэтому наивное понимание может привести к ошибочному выводу, что передача &mut T функции с параметром &T перемещает исходную ссылку и делает её недоступной.
Если бы Rust разрешал такое преобразование через обычное перемещение или позволял сохранять совместную ссылку без ограничений, можно было бы нарушить правило: пока существует активное чтение, изменение того же значения запрещено.
В позиции вызова Rust применяет coercion — специальное неявное приведение типов. Изменяемая ссылка &mut T превращается в совместное повторное заимствование &T, действующее в течение необходимого времени.
После завершения вызова это заимствование обычно заканчивается, поэтому исходную &mut T можно использовать снова. В современных версиях Rust точная граница заимствования определяется анализом последнего использования, известным как NLL — non-lexical lifetimes.
Вызов inspect(mutable_ref) не передаёт изменяемую ссылку как значение-владельца. Rust временно создаёт из неё совместный доступ к тому же i32; после вызова изменяемая ссылка снова может использоваться.
Пока совместное заимствование активно, через исходную ссылку нельзя изменять значение. Преобразование одностороннее: из &mut T можно получить &T, но из &T нельзя получить &mut T, поскольку неизменяемая ссылка сама по себе не гарантирует эксклюзивность.
Если совместная ссылка сохраняется в структуре или возвращается наружу, её время жизни может быть длиннее одного вызова. Тогда исходную изменяемую ссылку нельзя использовать для изменения значения до окончания действия сохранённого заимствования.
В библиотеке есть функция форматирования, которой требуется только чтение состояния. Рассматривались три варианта: принимать &mut T, принимать значение T или принимать &T.
Параметр &mut T излишне ограничил бы вызывающий код: функция получила бы право на изменение, хотя оно не нужно. Передача T могла бы переместить дорогое или невладеющее значение и сделала бы API менее универсальным.
Выбран &T. Вызывающий код может передать как &T, так и &mut T; во втором случае Rust создаёт временное совместное заимствование. Это сохраняет минимальные права функции, не требует копирования и оставляет возможность изменить значение после завершения чтения.
as?Нет. as предназначен для явных преобразований определённых типов, например числовых. Преобразование &mut T в &T относится к системе неявных приведений типов и обычно выполняется в специальных coercion-позициях, включая аргументы функций и инициализацию переменных с известным типом.
&mut T, пока функция получает &T?Нет, пока действует переданное совместное заимствование. Rust запрещает одновременно читать значение через &T и изменять его через &mut T; это ограничение относится к периоду действия заимствования, а не обязательно ко всему лексическому блоку.
&T?Совместное заимствование будет действовать столько, сколько требуется сохранённой ссылке. Исходную &mut T нельзя будет использовать для изменения значения до завершения этого периода. При этом передача всё равно не становится перемещением самой изменяемой ссылки: ограничивается её использование из-за активного заимствования.