Что перемещается при присваивании переменной типа &mut T другой переменной, и почему исходное имя после этого недоступно?
Перемещается сама изменяемая ссылка, то есть право единолично обращаться к объекту через неё; значение T при этом не перемещается и не копируется. После присваивания исходное имя недоступно, потому что &mut T не реализует Copy, а две активные изменяемые ссылки на один объект могли бы нарушить правило эксклюзивного доступа.
Модель владения Rust решает проблему безопасного управления памятью без обязательного сборщика мусора: предотвращает use-after-free, двойное освобождение и неконтролируемые гонки доступа. Заимствование позволяет временно передавать доступ к объекту, но этот доступ должен оставаться однозначным и проверяемым компилятором.
Отдельное владение самой ссылкой важно потому, что &mut T представляет не обычный адрес, а уникальный доступ к данным. Если бы такую ссылку можно было свободно копировать, из одной ссылки можно было бы получить несколько независимых каналов записи.
Рассмотрим ситуацию, когда одна переменная содержит &mut T, а затем эта ссылка присваивается другой переменной. Если после этого разрешить использовать оба имени, компилятор не смог бы гарантировать, что записи через них не пересекаются.
При этом перемещение ссылки не уничтожает объект и не передаёт владение самим значением T. Оно только передаёт другой переменной право использовать уже существующее изменяемое заимствование.
Операция присваивания переменной типа &mut T обычно является перемещением значения ссылки. У исходной переменной больше нет действующего значения, поэтому обращение к ней после присваивания запрещено. Объект, на который она указывает, продолжает жить у своего владельца и будет освобождён по обычным правилам владения.
Здесь перемещён дескриптор изменяемого заимствования first в second, а не число number. После перемещения first нельзя использовать, зато second сохраняет исключительный доступ к number.
Это отличается от повторного заимствования. Выражение вида &mut *first создаёт новое временное изменяемое заимствование объекта через уже имеющуюся ссылку; после завершения его использования исходную ссылку можно снова применять, если её заимствование завершилось.
Такое ограничение является компромиссом: код требует явнее управлять передачей изменяемого доступа, зато компилятор может доказать отсутствие одновременных конфликтующих записей без runtime-проверок. Для &T ситуация иная: неизменяемые ссылки реализуют Copy, поскольку несколько читателей не создают конфликта с точки зрения изменения данных.
Функция обработки получает &mut String, а вызывающий код хочет сохранить возможность использовать исходный доступ после обработки. Простая передача локальной переменной-ссылки может переместить саму ссылку, поэтому последующее обращение к исходному имени окажется ошибкой.
Варианты решения:
Обычно выбирают повторное заимствование или обычный вызов функции с ожидаемым &mut T: компилятор часто автоматически создаёт краткоживущий reborrow. В результате обработчик получает эксклюзивный доступ на время операции, а вызывающий код затем продолжает использовать исходную ссылку.
1. Реализует ли &mut T трейт Copy, если сам T реализует Copy?
Нет. Реализация Copy у T не делает &mut T копируемой ссылкой. Изменяемая ссылка намеренно не является Copy, потому что копирование создало бы несколько потенциально одновременно используемых прав на запись. Свойство копируемости значения и уникальность доступа через ссылку — разные аспекты типов.
2. Чем присваивание изменяемой ссылки отличается от выражения &mut *ссылка?
Присваивание переносит сам дескриптор ссылки в новую переменную, поэтому старое имя становится недействительным. &mut *ссылка создаёт новое заимствование того же объекта на основе существующего доступа; исходная ссылка временно недоступна, но может стать доступной после окончания нового заимствования. Это не копирование изменяемой ссылки, а контролируемое вложенное заимствование.
3. Освобождается ли объект T, когда перемещают &mut T?
Нет. Ссылка не владеет объектом и не вызывает его уничтожение при перемещении. Перемещается только право временного доступа, а время жизни объекта определяется его владельцем; например, локальное значение будет уничтожено при выходе владельца из области видимости, если оно не было перемещено дальше.