В Rust lifetimes определяют область видимости ссылок, чтобы компилятор мог убедиться, что указатели не висят в воздухе (нет висячих ссылок). Это позволяет гарантировать безопасность памяти во время компиляции без необходимости сборщика мусора.
Когда вы работаете со ссылками, Rust требует явно указать их время жизни, когда компилятор не может сам это вывести. Обычно это делается с помощью синтаксиса 'a:
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { if x.len() > y.len() { x } else { y } }
Здесь оба параметра и возвращаемое значение имеют одну и ту же lifetime, что гарантирует: возвращаемая ссылка не будет жить дольше, чем любой из аргументов.
Lifetimes не изменяют времени жизни данных, а лишь описывают его компилятору.
Можно ли вернуть ссылку на локальную переменную внутри функции?
Нет, нельзя: так как такая переменная будет уничтожена при выходе из функции. Пример:
fn foo() -> &String { // ошибка компиляции! let s = String::from("hello"); &s } // ссылка на s становится недействительной
Компилятор не даст собрать такой код: он защитит вас от использования ссылок на уничтоженные данные.
История
В команде появилось много утечек памяти, когда функции случайно возвращали ссылки на локальные буферы. Это не сработало, и спас только компилятор, который начал ругаться на lifetimes. Из-за частого появления таких ошибок было принято правило явно указывать lifetime, если функция работает со сложными структурами с вложенными ссылками.
История
В проекте был написан generics-код для кэширования данных. При неправильном проектировании lifetime generic-параметров возникали ошибки типа "cannot infer lifetime" и стало невозможно вывести время жизни данных, хранимых в кэше. Это приводило к настройке lifetime-аннотаций методом проб и ошибок, пока не было принято решение разделить кэшированные и некэшированные данные на разные структуры.
История
Один из коллег попытался реализовать пул соединений с использованием ссылок на объекты соединений, но не учитывал, что lifetimes соединений не совпадают с временем жизни пула. В итоге возникли висячие ссылки после освобождения соединений, что заметили лишь на этапе комплексного тестирования. После этого проект перешёл на безопасные обёртки (Arc<Mutex<T>>).