После главы 4 (было здесь) переходим к 10.3. Валидация ссылок при помощи времён жизни. Ну а куда еще… такие нынче времена. Для начала обозначим проблему, ради которой затеваются игры со временем. Простой пример висячей ссылки (dangling reference): Значение s будет создано в куче, затем уничтожено, а r — останется и будет ссылаться на то, чего нет. Rust отклонит такую заявку на выстрел в ногу с подробным пояснением, что s не живет достаточно долго: Но такие простые штуки давно ловятся и в других языках статическими анализаторами кода. Вот вариант посложнее, функция получает две ссылки на строки и возвращает ту, референт которой (то, на что указывает ссылка) длиннее: Вызывать будем так: r_longest получит, очевидно, ссылку на long_string и будет жить непозволительно долго (дольше своего референта) — такое в production попасть не должно.  В принципе, статический анализатор кода для C++ может и и такую ситуацию выловить — если "зайдет" внутрь вызываемой функции. Интересно, PVS-Studio справится с такой задачей, что скажет Andrey2008? Rust, однако, для проверки вызывающего кода смотрит только на сигнатуру того, что вызывается, внутрь не заглядывая. Посмотрим, как он это делает. Запускаем на компиляцию… Компилятор указывает нам, что сигнатура недостаточно информативна: Указание подробное и очень полезное. Нам говорят, что функция возвращает одолженное значение (т.е. ссылку), но непонятно, с каким параметром это одалживание связано — с x или y. Более того, компилятор даже предлагает способ починить объявление функции, введя параметр времени жизни (lifetime parameter). Итак, нам нужно аннотировать сигнатуру функции специальным образом, чтобы компилятор Rust "понял", с чем связано возвращаемое значение (у нас связано со всеми параметрами). Это делается при помощи generic lifetime parameters: Такое описание означает, что результат может быть связан как с x, так и с y, и после изменения примера компилятор ожидаемо в ожидаемом месте сообщает, что: Задание выполнено успешно. Но возникают два вопроса. Первый — а как сделать так, чтобы время жизни результата было связано, например, только со вторым параметром? Вот так: Но при этом функция перестанет компилироваться, так как мы в одной из веток if пытаемся возвратить x со временем жизни, не совпадающим с таковым для возвращаемого значения — как видим, машинерия Rust исправно работает. Второй вопрос (риторический) — а нельзя было "засахарить" синтаксис, вводить <'a> неявно и применять его по умолчанию ко всем параметрам и результатам, а у кого есть специальная нужда, тот пусть и указывает другие времена? С учетом уникальности имен параметров можно было бы вообще сделать как-то так (но это не точно): Сразу было бы ясно, что результат связан с параметром y и не имеет права этот параметр пережить ("outlive")... Впрочем, процесс засахаривания Rust идет, применительно к теме его результаты называются Lifetime Elision. Первое правило: Для каждого параметра-ссылки с неуказанным временем жизни заводится свой неявный параметр: Вместо занудного: можно писать менее занудно: Второе правило. Если в параметрах только одна ссылка, то ее время жизни переносится на все возвращаемые значения: Вместо: пишем: Вот это хорошо, конечно. Третье правило. Если в параметрах много ссылок, но одна из них &self или &mut self, то ее время жизни переносится на все возвращаемые значения Для методов все шикарно. Видимо, нас как бы подталкивают в сторону ООП (которого в Rust "по-настоящему" и нет, хе-хе). Под занавес надо разрешить загадку из первой части. Напомню, вот такой пример не компилируется: Результат: Компилятор закономерно жалуется, мол, неоткуда занять возвращаемое значение, все умерло (если конкретно — "умерла" локальная переменная s, ссылку на которую мы пытаемся возвратить). И опять предлагает решение! — обозначить время жизни возвращаемого значения как 'static. Делается так: Далее: Времена и структуры