Как аннотация времени жизни в сигнатуре функции связывает входную ссылку с возвращаемой?
Аннотация времени жизни задаёт не длительность жизни ссылки, а отношение между областями действия ссылок. Если входная и возвращаемая ссылки используют одну параметрическую жизнь, Rust требует, чтобы возвращаемая ссылка была действительна не дольше соответствующей входной ссылки; при нескольких входах фактическая связь ограничивается самым коротким подходящим временем жизни.
Аннотация не продлевает жизнь данных, не создаёт владельца и не влияет на выполнение программы. Она описывает ограничение, которое проверяет заимствователь.
Времена жизни появились как часть модели Rust, позволяющей совмещать низкоуровневый контроль памяти с проверкой безопасности во время компиляции. Исходная проблема — разрешить ссылки без сборщика мусора, но запретить висячие ссылки и использование данных после уничтожения владельца.
Аннотации нужны там, где связь между входными и выходными ссылками нельзя однозначно вывести из формы сигнатуры. Они делают контракт заимствования явным для компилятора и читателя.
Функция может вернуть ссылку на данные, принадлежащие вызывающему коду. Компилятор должен проверить, что эта ссылка не переживёт данные, на которые она указывает.
Ошибка в рассуждении часто выглядит так: разработчик считает, что одна аннотация означает «ссылка живёт столько, сколько указано в 'a». На самом деле 'a — параметр связи, а конкретная область действия выбирается из контекста вызова и ограничивается временем жизни всех участвующих заимствований.
Сигнатура с одинаковой аннотацией у входной и выходной ссылок выражает зависимость: результат связан с входными данными и не может использоваться дольше разрешённого времени жизни этого заимствования. При двух входах с одной 'a результат должен быть корректен для общего диапазона, совместимого с обоими входами; практически это часто означает ограничение самым коротким временем жизни.
Здесь 'a не делает temporary долгоживущим. Напротив, возвращаемая ссылка считается связанной с областью, в которой оба заимствования допустимы, поэтому использование result после уничтожения temporary запрещено.
Если функция фактически возвращает только первый аргумент, более точный контракт может связать результат только с ним, а время жизни второго аргумента описать независимо. Это уменьшает ограничения для вызывающего кода, но требует корректно выразить реальную логику функции; аннотации нельзя использовать для обхода проверки безопасности.
Отдельные параметры времени жизни нужны, когда входные ссылки не обязаны иметь одну общую связь с результатом. При этом аннотации не всегда требуются явно: правила элиминации времён жизни автоматически выводят типичные связи в простых сигнатурах, например для метода, возвращающего ссылку, связанную с self.
В утилите разбора конфигурации функция принимала буфер и необязательный разделитель, а возвращала фрагмент буфера. Первоначально оба входа и результат были связаны одной 'a. Это было безопасно, но излишне ограничивало вызов: короткоживущий разделитель не позволял сохранить результат, хотя фактически результат никогда не ссылался на разделитель.
Рассматривались два варианта. Можно было клонировать возвращаемую строку, что упрощало времена жизни, но добавляло выделение памяти и копирование. Можно было уточнить контракт и связать результат только с буфером, сохранив разделитель отдельным заимствованием; этот вариант требовал более точного анализа, но не имел лишних затрат.
Выбрали второй вариант, потому что функция действительно возвращала срез исходного буфера и не зависела от времени жизни разделителя. В результате код сохранил нулевое копирование, а вызывающий код получил возможность использовать результат после завершения области действия временного разделителя.
'a, что все ссылки живут ровно одинаковое время?Нет. 'a обозначает параметр отношения, а не фиксированную продолжительность. В конкретном вызове компилятор выбирает область, совместимую с ограничениями всех ссылок; она может быть короче фактической жизни одного из аргументов. Поэтому две ссылки с одной 'a могут указывать на данные, владельцы которых существуют разное время, если выбранная общая область допустима для обеих.
Нет. Аннотация только описывает допустимое заимствование. Владелец локальных данных всё равно уничтожается при выходе из своей области действия, и ссылка наружу будет отклонена, если способна пережить владельца. Чтобы результат жил дольше, нужно изменить владение, например вернуть значение с передачей владения или создать независимую копию.
'a?Одна общая 'a выражает более сильное ограничение: входы рассматриваются как участвующие в одной связи с результатом. Несколько параметров позволяют показать независимость источников и не привязать результат к сроку жизни аргумента, который на него не влияет.
Это не означает автоматического разрешения любой комбинации ссылок: тело функции всё равно должно быть безопасным, а возвращаемая ссылка — указывать на данные, которые действительно переживают её использование. Раздельные параметры полезны как средство точного контракта, а не как способ ослабить правила заимствования.