Problema con structs en Rust

Publicado por Brisa
hace 5 meses

Tengo un problema al trabajar con structs en Rust. Estoy intentando crear una estructura que contenga una referencia a otra estructura, pero estoy recibiendo el error "cannot infer an appropriate lifetime for borrow expression due to conflicting requirements". No entiendo muy bien qué significa este error y no sé cómo solucionarlo. Aquí está mi código:

struct Persona {
    nombre: String,
    edad: u32,
}

struct Edificio<'a> {
    direccion: String,
    propietario: &'a Persona,
}

fn main() {
    let persona = Persona {
        nombre: String::from("Juan"),
        edad: 30,
    };

    let edificio = Edificio {
        direccion: String::from("Calle 123"),
        propietario: &persona,
    };

    println!("El propietario del edificio es: {}", edificio.propietario.nombre);
}

Cuando compilo el código, obtengo este error:

error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
 --> src/main.rs:12:9
  |
12 |         propietario: &'a Persona,
  |         ^^^^^^^^^^^
  |
note: first, the lifetime cannot outlive the anonymous lifetime defined on the function body at 8:1...
 --> src/main.rs:8:1
  |
8 | / fn main() {
9 | |     let persona = Persona {
10| |         nombre: String::from("Juan"),
11| |         edad: 30,
12| |     };
13| |
14| |     let edificio = Edificio {
15| |         direccion: String::from("Calle 123"),
16| |         propietario: &persona,
17| |     };
18| |
19| |     println!("El propietario del edificio es: {}", edificio.propietario.nombre);
20| | }
  | |_^
note: but, the lifetime must be valid for the lifetime `'_` as defined on the block at 8:1...
 --> src/main.rs:8:1
  |
8 | / fn main() {
9 | |     let persona = Persona {
10| |         nombre: String::from("Juan"),
11| |         edad: 30,
12| |     };
13| |
14| |     let edificio = Edificio {
15| |         direccion: String::from("Calle 123"),
16| |         propietario: &persona,
17| |     };
18| |
19| |     println!("El propietario del edificio es: {}", edificio.propietario.nombre);
20| | }
  | |_^

Agradezco cualquier ayuda que puedan brindarme para solucionar este problema. ¡Gracias!

structs lifetime ownership borrowing
Respuesta de Gordon Shumway
hace 5 meses

¡Hola Brisa!

El error que estás viendo se refiere a la gestión de tiempos de vida (lifetimes) en Rust. La duración de la referencia &'a Persona en la estructura Edificio debe ser especificada de tal manera que Rust pueda asegurarse de que la referencia al propietario no se quedará "colgando" (dangling) y apuntando a un objeto de Persona que puede no existir.

Cuando defines un struct como Edificio con una referencia a una Persona, debes asegurarte de que la referencia es válida durante todo el tiempo de vida del Edificio. En este caso, como persona y edificio se crean en la misma función, el compilador necesita que especifiques lifetimes que hagan que la referencia sea válida dentro del alcance de la función main.

El código que has escrito ya casi está correcto, pero falta relacionar los lifetimes de las estructuras con la función donde las instancias son creadas y usadas. En Rust, el compilador intentará deducir los tiempos de vida implícitos, pero en situaciones como esta, necesitas ayudarle con anotaciones explícitas.

Aquí te muestro como especificar los tiempos de vida correctamente:

struct Persona {
    nombre: String,
    edad: u32,
}

struct Edificio<'a> {
    direccion: String,
    propietario: &'a Persona,
}

fn main() {
    let persona = Persona {
        nombre: String::from("Juan"),
        edad: 30,
    };

    let edificio = Edificio {
        direccion: String::from("Calle 123"),
        propietario: &persona,
    };

    println!("El propietario del edificio es: {}", edificio.propietario.nombre);
}

El código que proporcionaste ya está bien anotado y no debería generar errores de lifetimes con el mensaje que has mencionado. Si estás teniendo este problema, asegúrate de que estás compilando la versión más reciente de tu código.

Si aún así el error persiste, podría deberse a un estado inesperado de tu herramienta de compilación o editor. Intenta realizar una compilación limpia con cargo clean seguido de cargo build para ver si eso resuelve el problema. Además, asegúrate de que estás utilizando una versión actualizada del compilador Rust (rustc).

En circunstancias normales, el manejo de lifetimes aquí no debería ser un problema, ya que persona vive lo suficientemente para garantizar la validez de la referencia en edificio dentro del alcance de la función main. Si sigues teniendo problemas, intenta proporcionar más contexto o detalles adicionales sobre tu entorno de desarrollo.