Static
В Rust есть несколько зарезервированных имён времени жизни. Одно из них — 'static
. Вы можете столкнуться с ним в двух случаях:
#![allow(unused)] fn main() { // Ссылка с временем жизни 'static: let s: &'static str = "hello world"; // 'static как часть ограничения типажа: fn generic<T>(x: T) where T: 'static {} }
Оба они похожи, но немного отличаются, что часто вызывает путаницу при изучении Rust. Вот несколько примеров для каждой ситуации:
Время жизни ссылки
'static
как время жизни ссылки означает, что данные, на которые указывает ссылка, живут в течение всего времени жизни работающей программы. В тоже время, этот срок может быть сокращён принудительно.
Есть два способа создать переменную с временем жизни 'static
, и оба они лежат в области "только для чтения" бинарного файла:
- Создание константы с ключевым словом
static
. - Создание
строкового
литерала, который имеет тип &'static str.
Рассмотрим следующий пример, который показывает оба метода:
// Создадим константу со временем жизни `'static`. static NUM: i32 = 18; // Вернём ссылку на `NUM`, у которой собственное время жизни `'static` // приводится ко времени жизни аргумента. fn coerce_static<'a>(_: &'a i32) -> &'a i32 { &NUM } fn main() { { // Создадим *строковый* литерал и выведем его: let static_string = "Я в неизменяемой памяти"; println!("static_string: {}", static_string); // Когда `static_string` выходит из области видимости, ссылка // на неё больше не может быть использована, но данные остаются в бинарном файле. } { // Создадим число для использования в `coerce_static`: let lifetime_num = 9; // Приведём `NUM` ко времени жизни `lifetime_num`: let coerced_static = coerce_static(&lifetime_num); println!("coerced_static: {}", coerced_static); } println!("NUM: {} остаётся доступным!", NUM); }
Ограничение типажа
Как ограничение типажа, это означает, что тип не содержит нестатических ссылок. Например. получатель может хранить тип столько, сколько захочет, и тип никогда не станет недействительным, пока получатель его не удалит.
Важно понимать, что это означает, что любые владеющие данные всегда проходят проверку на ограничение времени жизни 'static
, но ссылка на эти владеющие данные обычно не проходит:
use std::fmt::Debug; fn print_it( input: impl Debug + 'static ) { println!( "Переданное значение 'static равно: {:?}", input ); } fn main() { // I владеемое и не имеет ссылок, следовательно является 'static: let i = 5; print_it(i); // Упс, &I имеет время жизни, ограниченное областью видимости // main(), поэтому оно не 'static: print_it(&i); }
Компилятор скажет вам:
error[E0597]: `i` does not live long enough
--> src/lib.rs:15:15
|
15 | print_it(&i);
| ---------^^--
| | |
| | borrowed value does not live long enough
| argument requires that `i` is borrowed for `'static`
16 | }
| - `i` dropped here while still borrowed