Ответ 1
В вашем примере [1, 2, 3]
не обрабатывается как локальная переменная, а как статическая!
Давайте посмотрим на этот код:
fn foo() -> &'static [i32] {
&[1, 2, 3]
}
Это работает!
Некоторое время назад RFC 1414: Статическое продвижение Rvalue было объединено: "Повышать значения 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_char() -> &'static char {
&'c'
}
struct Foo(char);
fn promote_struct() -> &'static Foo {
&Foo('x')
}
Помимо литералов, это также работает для небольшого числа функций в стандартной библиотеке, но они, вероятно, были ошибкой. Решение о том, можно ли автоматически преобразовать результат произвольных const
функций в static
, остается открытой темой.