Невозможно вернуть статическую ссылку на временный массив, даже если массив содержит значение, которое также имеет статическое время жизни - PullRequest
0 голосов
/ 24 декабря 2018

Значение, возвращаемое из T::bar, имеет время жизни 'static, поэтому области действия Test2::foo не нужно ничего владеть.Возвращать &[T::bar()] как &'static [&'static StructType] должно быть безопасно?Test:foo компилируется без проблем, поэтому я ожидал, что Test2::foo также будет компилироваться.

Код

pub struct StructType {
    a: &'static str,
}

pub trait Foo {
    fn foo() -> &'static [&'static StructType];
    fn bar() -> &'static StructType;
}

pub struct Test;

impl Foo for Test {
    fn foo() -> &'static [&'static StructType] {
        &[&StructType { a: "asdf" }]
    }

    fn bar() -> &'static StructType {
        &StructType { a: "asdf" }
    }
}

pub struct Test2<T: Foo>(T);

impl<T: Foo> Test2<T> {
    pub fn foo() -> &'static [&'static StructType] {
        &[T::bar()]
    }
}

детская площадка

Ошибка

error[E0515]: cannot return reference to temporary value
  --> src/lib.rs:26:9
   |
26 |         &[T::bar()]
   |         ^----------
   |         ||
   |         |temporary value created here
   |         returns a reference to data owned by the current function

Ответы [ 2 ]

0 голосов
/ 24 декабря 2018

RFC , который добавил автоматическое продвижение ссылок на значения в 'static состояния:

Повышение значений constexpr для значений в статической памяти вместо стековых слотов и предоставлениев языке, поскольку они могут напрямую создавать статические ссылки на них.

Литеральные значения являются наиболее очевидными константными выражениями.Тем не менее, вызов функции не константный, если явно не помечен как таковой с использованием const.Однако, начиная с Rust 1.31, типы операций, которые доступны в пользовательской функции const, довольно ограничены.Допустимы литеральные значения:

const fn bar() -> &'static StructType {
    &StructType("asdf")
}

const fn combo() -> &'static [&'static StructType; 1] {
    &[Self::bar()]
}

Преобразование из ссылки на массив в срез не разрешено в функции const, поэтому она должна быть в другой функции.:

fn wombo() -> &'static [&'static StructType] {
    Self::combo()
}

Кроме того, вы не можете определять const функции в признаке.

См. Также:

Что мне действительно нужно: 1) иметь T::bar() возвращать константу, 2) иметь Test:foo возвращать константу массива, которая построена изT::bar() и U::bar() и U, T являются общими параметрами для Test

Вы не можете сделать это

fn example<T>() {
    static NO_CAN_DO: T = unimplemented!();
}
error[E0401]: can't use type parameters from outer function
 --> src/lib.rs:2:23
  |
1 | fn example<T>() {
  |    ------- - type variable from outer function
  |    |
  |    try adding a local type parameter in this method instead
2 |     static NO_CAN_DO: T = unimplemented!();
  |                       ^ use of type variable from outer function

См. Также:

0 голосов
/ 24 декабря 2018

Я думаю, что вы думаете о жизнях неправильно.Кажется, что вы используете их, чтобы «объявить», как долго вы хотите, чтобы он жил, но вы не можете изменить время жизни ссылки.Все описатели времени жизни помогают компилятору понять время жизни в тех случаях, когда у него нет информации, чтобы исключить его.

Глава 15.4.7 Static from Rust by Example помочь вам.

По сути, есть только два способа создания 'static данных:

  1. Создание константы с объявлением static.
  2. Создайте строковый литерал, который имеет тип: &'static str.

Вы можете достичь того же, что и выше, объявив описатели времени жизни, как вы обычно делаете в Rust (но компилятор предложил время жизни 'static, так как выне объявлял никаких жизней сам).См. Ниже.

Суть в том, что, за исключением &'static str, время жизни никогда не может быть изменено путем указания времени жизни в ваших функциях.Когда вы пишете &[T::bar()], массив не является константой и будет отброшен, когда вы покинете область действия своей функции.Если вы хотите, чтобы он жил с 'static временем жизни, вам нужно сделать его константой, как я покажу ниже.

Теперь это, вероятно, не совсем то, что вы хотели сделать, но это скомпилируется, и я надеюсь объяснитьразница:

const ARR: &'static [&'static StructType] = &[&StructType { a: "asdf" }];

pub struct StructType {
    a: &'static str,
}

pub trait Foo<'a> {
    fn foo() -> &'a [&'a StructType];
    fn bar() -> &'a StructType;
}

pub struct Test;

impl<'a> Foo<'a> for Test {
    fn foo() -> &'a [&'a StructType] {
        &[&StructType { a: "asdf" }]
    }

    fn bar() -> &'a StructType {
        &StructType { a: "asdf" }
    }
}

pub struct Test2<T: Foo<'static>>(T);

impl<T: Foo<'static>> Test2<T> {
    pub fn foo() -> &'static [&'static StructType] {
        ARR
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...