Как параметр времени жизни в объявлении реализации трейта влияет на то, к каким ссылочным типам применима эта реализация?
Параметр времени жизни в реализации трейта участвует в сопоставлении типа: он связывается со временем жизни ссылки в реализуемом типе. Поэтому реализация может быть доступна для ссылок с любой длительностью либо только для ссылок, удовлетворяющих дополнительному ограничению, например 'a: 'static.
Сам параметр не продлевает заимствование и не задаёт фактический срок жизни значения. Он описывает условие, при котором компилятор может выбрать данную реализацию.
В Rust реализация трейта должна быть проверяема статически для каждого конкретного типа. Для ссылочных типов одного имени базового типа недостаточно: ссылка включает ещё и время жизни, от которого зависят допустимость хранения, передачи и вызова методов.
Параметры времени жизни в impl позволяют выразить такие зависимости без runtime-механизмов. Это часть системы типов и проверки заимствований, а не средство управления памятью во время выполнения.
Предположим, трейт должен быть доступен для любого строкового заимствования. Если реализация не связывает параметр времени жизни с типом ссылки, невозможно точно описать, для каких экземпляров она действует.
Обратная ситуация тоже важна: иногда API должен принимать только значения со ссылками, способными пережить 'static. Ошибка в ограничении может либо необоснованно отвергнуть безопасные вызовы, либо открыть реализацию для слишком коротких заимствований.
В объявлении реализации параметр времени жизни связывается с конкретной частью реализуемого типа. Например, реализация для &'a str означает: трейт реализован для ссылочного типа с некоторым временем жизни 'a. При проверке конкретного вызова компилятор подставляет фактическое время жизни ссылки и проверяет все ограничения.
Первая реализация применима к &str с любой подходящей длительностью заимствования. Вторая требует, чтобы 'a длилось не меньше 'static; практически это означает, что ссылка должна быть статической. Строковый литерал подходит, а ссылка на локальную String — нет.
Ограничение 'a: 'static не превращает локальную ссылку в статическую. Оно только отбирает типы, которые уже удовлетворяют этому требованию. Аналогично, объявление impl<'a> не означает, что реализация создаётся отдельно как исполняемый объект для каждого времени жизни: после проверки времени жизни не представлены отдельными runtime-значениями.
Важно отличать параметр реализации от времени жизни временного заимствования внутри метода. Вызов метода может создать более короткое заимствование самого объекта, даже если тип, для которого найден impl, содержит ссылку с более долгим временем жизни.
Если несколько реализаций подходят одному типу, они не должны пересекаться. Поэтому нельзя без дополнительного различимого условия объявить одновременно общую реализацию для всех 'a и более узкую реализацию для 'a: 'static: такие реализации обычно считаются пересекающимися и нарушают правила coherence.
Представим API маркеров для данных, которые разрешено помещать в глобальный кэш. Для любого заимствованного текста можно реализовать общий трейт анализа, но трейт, разрешающий глобальное хранение, должен применяться только к ссылкам, не зависящим от локального стека.
Вариант с реализацией для любого 'a проще, но небезопасен на уровне контракта: он позволит передать в API ссылку, которая скоро станет недействительной. Вариант с требованием 'a: 'static безопаснее, однако ограничивает применимость и может потребовать владения данными вместо заимствования.
Выбранное решение — отдельная реализация с явным ограничением 'a: 'static. В результате компилятор отвергает локальные ссылки на этапе проверки типов, а подходящие статические данные проходят без дополнительных проверок времени выполнения.
impl<'a> обязательное существование именно долгоживущей ссылки?Нет. 'a — параметр, который будет конкретизирован при использовании реализации. Если ограничений нет, он может обозначать короткое время жизни локального заимствования. Долгий срок появляется только из типа или дополнительных bound-ограничений, а не из самого факта записи impl<'a>.
impl продлить жизнь объекта?Нет. Bound только проверяет уже существующее отношение между временами жизни. Если ссылка на локальное значение заканчивается при выходе из блока, условие реализации не изменит это поведение и не позволит хранить ссылку дольше исходного значения.
&'a T не означает реализацию для самого T?Потому что ссылка и значение — разные типы. Реализация для &'a T выбирается только когда тип аргумента является ссылкой; передача самого T требует отдельной реализации или другого ограничения. Это различие позволяет API по-разному задавать требования к владению и заимствованию.