Error al utilizar structs anidados en Rust (Advanced, Structs, Error)

Publicado por Brisa
hace 4 meses

Estoy teniendo un problema al utilizar structs anidados en Rust y no puedo encontrar una solución. Agradezco cualquier ayuda que puedan brindarme.

Aquí está el código que estoy utilizando:

struct Coordenadas {
    latitud: f64,
    longitud: f64,
}

struct Persona {
    nombre: String,
    coordenadas: Coordenadas,
}

fn main() {
    let coordenadas = Coordenadas {
        latitud: 42.3601,
        longitud: -71.0589,
    };

    let p = Persona {
        nombre: String::from("Alice"),
        coordenadas: coordenadas,
    };

    println!("El nombre de la persona es: {}", p.nombre);
    println!("Las coordenadas son: {}, {}", p.coordenadas.latitud, p.coordenadas.longitud);
}

Al intentar compilar el código, obtengo el siguiente error:

error[E0507]: cannot move out of borrowed content
   --> src/main.rs:20:28
    |
20  |         coordenadas: coordenadas,
    |                            ^^^^^^^^^
    |                            |
    |                            move occurs because `coordenadas` has type `Coordenadas`, which does not implement the `Copy` trait

Creo que el error tiene que ver con el movimiento de coordenadas dentro de la estructura Persona, pero no estoy seguro de cómo solucionarlo. ¿Alguien tiene alguna idea de cómo podría resolver este problema?

¡Gracias de antemano por su ayuda!

Hola a todos
Respuesta de Gordon Shumway
hace 4 meses

¡Hola Brisa!

El error que estás viendo es un resultado de cómo Rust maneja la propiedad de los valores. Por defecto, cuando pasas un valor a otra variable o función, Rust realiza un "move" de la propiedad del valor, a menos que el tipo del valor implemente el trait Copy, el cual indica que el valor se puede copiar de manera segura sin preocuparse por la propiedad o la memoria. Los tipos como i32, f64 y bool son Copy, pero estructuras más complejas como String o tu Coordenadas no lo son a menos que lo especifiques manualmente.

Entonces, cuando intentas usar coordenadas para crear la instancia de Persona, estás moviendo la propiedad de coordenadas y después intentando usarla, lo cual no está permitido.

Para solucionar esto, tienes un par de opciones:

  1. Implementar Clone y clonar coordenadas cuando la utilices para construir Persona.
  2. Implementar Copy y Clone para Coordenadas para que puedan ser copiadas en vez de movidas.

Dado que f64 sí tiene el trait Copy y Coordenadas solo consta de tipos que son Copy, puedes hacer que Coordenadas también sea Copy. Así es cómo se vería la solución:

#[derive(Copy, Clone)] // Agregamos los derives aquí
struct Coordenadas {
    latitud: f64,
    longitud: f64,
}

struct Persona {
    nombre: String,
    coordenadas: Coordenadas,
}

fn main() {
    let coordenadas = Coordenadas {
        latitud: 42.3601,
        longitud: -71.0589,
    };

    let p = Persona {
        nombre: String::from("Alice"),
        coordenadas: coordenadas, // Ahora puedes copiar `coordenadas` sin problema
    };

    println!("El nombre de la persona es: {}", p.nombre);
    println!("Las coordenadas son: {}, {}", p.coordenadas.latitud, p.coordenadas.longitud);
}

Con eso debería compilar sin problemas porque ahora coordenadas se copia en lugar de moverse, lo cual significa que puedes seguir usándolas después de crear p sin preocuparte por la propiedad o movimientos. ¡Espero que esto resuelva tu problema!