Неявное преобразование в stati c время жизни в любом случае :: Error - PullRequest
0 голосов
/ 07 августа 2020

Я читал код для anyhow crate в Rust. Существует конкретная строка Я не полностью обработал asp:

{
 let vtable = &ErrorVTable { ... };
 construct(vtable, ...);
}

fn construct(vtable: &'static ErrorVTable, ...);

Кажется, мы создаем структуру ErrorVTable и возвращаем ссылку на нее, которая имеет время жизни ` stati c. Я ожидал, что компилятор создаст структуру в стеке функций и вернет ссылку на нее, что вызовет странные проблемы с памятью.

Но похоже, что компилятор обнаруживает, что эта переменная для всех возможных E вычисленных во время компиляции и как-нибудь создает для них стати c переменные? Как это на самом деле работает?

1 Ответ

2 голосов
/ 07 августа 2020

Рассмотрим этот упрощенный код:

struct Foo {
    x: i32
}

fn test(_: &'static Foo) {}

fn main() {
    let f = Foo{ x: 42 };
    test(&f);
}

Как и ожидалось, он не компилируется с сообщением:

f не живет достаточно долго

Однако это небольшое изменение действительно компилируется:

fn main() {
    let f = &Foo{ x: 42 };
    test(f);
}

Разница в том, что в первом случае объект Foo является локальным, с локальным временем жизни, поэтому ссылка 'static не может быть построен. Но в последнем случае фактический объект является статической c константой, поэтому он имеет статическое c время жизни, а f является просто ссылкой на него.

Чтобы увидеть разницу, рассмотрим этот другой эквивалентный код:

const F: Foo = Foo{ x: 42 };
fn main() {
    test(&F);
}

Или, если вы используете фактический константный литерал:

fn test_2(_: &'static i32) {}
fn main() {
    let i = &42;
    test_2(&i);
}

Естественно, это работает, только если все аргументы конструкции Foo постоянны. Если какое-либо значение не является константой, компилятор автоматически переключится на локальное временное значение вместо константы stati c, и вы потеряете время жизни 'static.

Точные правила для этого постоянное продвижение , как его иногда называют, немного сложнее и может быть расширено в новых версиях компилятора.

...