reference - ¿Por qué puedo devolver una referencia a un literal local pero no a una variable?
rust borrow-checker (1)
En su ejemplo,
[1, 2, 3]
no se trata como una variable local, sino como una variable estática.
Echemos un vistazo a este código:
fn foo() -> &''static [i32] {
&[1, 2, 3]
}
¡Esto funciona!
Hace algún tiempo,
RFC 1414: Rvalue Static Promotion
se fusionó: "Promover valores constexpr a valores en memoria estática en lugar de ranuras de pila".
Esto significa que básicamente todos los literales que escribes pueden vivir para siempre.
Por lo tanto, cosas como
let _: &''static i32 = &42;
¡Además trabajo!
Si evitamos usar una matriz literal, podemos ver el error esperado:
fn bar() -> impl Iterator<Item = i32> {
vec![1, 2, 3].iter().map(|&i| i)
}
Aquí obtenemos el error "
v
no vive lo suficiente".
Esto no está limitado a enteros o matrices; se aplica ampliamente a cualquier literal que se compone únicamente de literales:
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'')
}
Más allá de los literales, esto también funciona para una
pequeña
cantidad de funciones en la biblioteca estándar,
pero probablemente fueron un error
.
Decidir si el resultado de las funciones
const
arbitrarias se puede promocionar automáticamente a
static
sigue siendo un
tema abierto
.
¿Por qué se compila este código?
fn get_iter() -> impl Iterator<Item = i32> {
[1, 2, 3].iter().map(|&i| i)
}
fn main() {
let _it = get_iter();
}
[1, 2, 3]
es una variable local y
iter()
toma prestada.
Este código no debe compilarse porque el valor devuelto contiene una referencia a una variable local.