Почему я могу вернуть ссылку на локальный литерал, но не на переменную? - PullRequest
0 голосов
/ 15 мая 2018

Почему этот код компилируется?

fn get_iter() -> impl Iterator<Item = i32> {
    [1, 2, 3].iter().map(|&i| i)
}

fn main() {
    let _it = get_iter();
}

[1, 2, 3] является локальной переменной и iter() заимствует ее.Этот код не должен компилироваться, поскольку возвращаемое значение содержит ссылку на локальную переменную.

1 Ответ

0 голосов
/ 15 мая 2018

В вашем примере [1, 2, 3] не обрабатывается как локальная переменная, а как статическая!

Давайте посмотрим на этот код:

fn foo() -> &'static [i32] {
    &[1, 2, 3]
}

Это работает!

Некоторое время назад, RFC 1414: Rvalue Static Promotion было объединено: «Повышать значения constexpr для значений в статической памяти вместо слотов стека».Это означает, что в основном все написанные вами литералы могут жить вечно.Таким образом, такие вещи, как let _: &'static i32 = &42; также работают!

Если мы избегаем использования литерального массива, мы можем увидеть ожидаемую ошибку:

fn bar() -> impl Iterator<Item = i32> {
    vec![1, 2, 3].iter().map(|&i| i)
}

Здесь мы получаем "v неошибка "живи достаточно долго".

Это не ограничивается целыми числами или массивами;это широко применяется к любому литералу, который состоит исключительно из литералов:

fn promote_integer() -> &'static i32 {
    &42
}
fn promote_float() -> &'static f64 {
    &42.42
}
fn promote_str() -> &'static str {
    "Hello World!"
}
struct Foo(char);

fn promote_struct() -> &'static Foo {
    &Foo('x')
}

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

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