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

Смотрите также:

'static константы