При сопоставлении структуры шаблон с ..: какие поля он оставляет несвязанными и как это влияет на владение?
Шаблон с .. явно сопоставляет только указанные поля, а остальные проверяет без создания для них имён. Несвязанные поля не перемещаются в отдельные переменные, но при сопоставлении самой структуры по значению исходное значение всё равно может стать частично перемещённым, если явно связанное поле не реализует Copy.
Деструктурирование в Rust позволяет извлекать только те части значения, которые нужны алгоритму. Синтаксис .. решает практическую проблему многопольных структур: код не обязан перечислять и отдельно обрабатывать каждое поле.
Это также делает шаблоны менее хрупкими при добавлении новых полей в структуру: шаблон с .. продолжает явно описывать только интересующие поля.
Без .. структурный шаблон должен охватить все поля, иначе компилятор отклонит его как неполный. Попытка перечислить все поля ради полноты может привести к ненужным перемещениям, усложнить код и связать его с деталями структуры, которые алгоритму не нужны.
Важно различать отсутствие связывания и отсутствие владения. .. не создаёт переменную для оставшихся полей, однако он не превращает сопоставление по значению в сопоставление по ссылке.
В шаблоне структуры имена полей слева от .. связываются обычным способом. Если структура сопоставляется по значению, поле типа, не реализующего Copy, обычно перемещается в новую переменную; поле типа Copy копируется. Поля, скрытые за .., не извлекаются в переменные.
Здесь id копируется, а body и priority не связываются. Если бы явно связывалось поле body, оно было бы перемещено, и использование всей переменной message после этого стало бы недопустимым из-за частичного перемещения.
При сопоставлении по ссылке владение не меняется: связанные поля становятся ссылками или ссылочными представлениями в зависимости от контекста. Поэтому для чтения части большой структуры обычно безопаснее сопоставлять ссылку, а не само значение.
.. нельзя использовать как способ получить «остаток структуры» в отдельное значение. Он только обозначает все неупомянутые поля; агрегированного объекта с ними не создаётся.
Обработчику сообщения нужен только его идентификатор, а тело может быть большим и владеть буфером. Вариант с сопоставлением самого сообщения и явным связыванием тела создаёт ненужное перемещение и может помешать дальнейшему использованию сообщения.
Можно перечислить все поля, но это ухудшает сопровождаемость: при добавлении поля шаблон придётся изменять. Можно сопоставить ссылку на структуру с ..: это сохраняет владение сообщением и не требует перечислять ненужные поля.
Предпочтительное решение — работать со ссылкой и связывать только нужный идентификатор. Оно не перемещает буферы, устойчиво к добавлению полей и ясно показывает, что обработчик не забирает владение сообщением.
.. отличается от _ в шаблоне структуры?_ игнорирует одно конкретное значение или поле, тогда как .. обозначает сразу все поля структуры, которые не были перечислены. Например, запись поля с _ всё ещё требует назвать это поле, а .. позволяет не перечислять остальные поля вообще. Ни один из этих вариантов не создаёт доступного имени для проигнорированного значения.
..?Это зависит от того, были ли другие поля перемещены. Само .. не перемещает скрытые поля, поэтому при отсутствии перемещённых несоответствующих полей доступ к ним может сохраниться. Но если другое явно связанное поле было перемещено, структура становится частично перемещённой: использовать её целиком нельзя, хотя отдельные не перемещённые поля могут оставаться доступными.
Надёжный способ избежать таких тонкостей — сопоставлять ссылку на структуру, когда требуется только чтение.
.. нельзя произвольно применять к структуре с Drop?Тип, реализующий Drop, должен быть уничтожен как целое, поэтому Rust запрещает перемещать из него отдельные поля. Иначе его метод drop получил бы значение с нарушенным состоянием владения.
Сопоставление такой структуры по ссылке остаётся допустимым: поля лишь заимствуются, а владельцем структуры по-прежнему остаётся исходная переменная. Если нужно извлечь поле по значению, обычно применяют явный метод, который безопасно потребляет всю структуру и сам определяет порядок извлечения данных.