Почему получение статической ссылки на const возвращает ссылку на временную переменную? - PullRequest
2 голосов
/ 29 марта 2019

В Rust у меня есть следующий код:

pub trait Test: Sized {
    const CONST: Self;
    fn static_ref() -> &'static Self {
        &Self::CONST
    }
}

Я ожидаю, что, поскольку const равно 'static, тогда я смогу сослаться на него, который также 'static. Однако компилятор выдает следующую ошибку:

error[E0515]: cannot return reference to temporary value
   --> file.rs:9:9
    |
  9 |         &Self::CONST
    |         ^-----------
    |         ||
    |         |temporary value created here
    |         returns a reference to data owned by the current function

Как здесь вводится временная переменная?

Кроме того, кажется, что в некоторых случаях ссылка на константу работает. Вот короткий конкретный пример с немного отличной реализацией Test

pub trait Test: Sized {
    fn static_ref() -> &'static Self;
}

struct X;

impl Test for X {
    fn static_ref() -> &'static Self {
        &X
    }
}

Ответы [ 2 ]

7 голосов
/ 29 марта 2019

A constant в Rust - это константа времени компиляции, а не фактическая переменная с местом в памяти. Компилятор Rust может заменить фактическое значение константы, где бы он ни использовался. Если вы берете адрес такого значения, вы получаете временный адрес.

Rust также имеет концепцию статической переменной . Эти переменные на самом деле имеют места в памяти, которые являются постоянными на протяжении всей программы, и использование ссылки на статическую переменную действительно приводит к ссылке с 'static продолжительностью жизни.

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

3 голосов
/ 29 марта 2019

Когда вы определяете черту, определение должно иметь смысл для всех возможных реализаций.

Проблема может быть не сразу ясна без примера, где она терпит неудачу. Предположим, у вас был такой тип:

struct MyStruct;
impl MyStruct {
    const fn new() -> Self {
        MyStruct
    }
}

И вы попытались реализовать эту черту следующим образом:

impl Test for MyStruct {
    const CONST: Self = MyStruct::new();
}

Это не сработает, потому что реализация static_ref теперь будет выглядеть так:

fn static_ref() -> &'static Self {
    // &Self::CONST
    &MyStruct::new()
}

Это создает значение внутри функции и пытается вернуть его. Это значение не статическое, поэтому время жизни 'static недопустимо.


Однако, немного перенастроив, вы можете заставить что-то работать:

pub trait Test: Sized + 'static {
    // This is now a reference instead of a value:
    const CONST: &'static Self;
    fn static_ref() -> &'static Self {
        Self::CONST
    }
}

struct MyStruct;
impl MyStruct {
    const fn new() -> Self {
        MyStruct
    }
}

impl Test for MyStruct {
    const CONST: &'static Self = &MyStruct::new();
}

Это работает, потому что CONST уже является ссылкой 'static, поэтому функция может просто вернуть ее. Все возможные реализации должны иметь возможность получить 'static ссылку на Self для реализации черты, поэтому больше не возникает проблема со ссылкой на какое-то произвольное локальное значение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...