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