No puedo resolver el error de borrowing en Rust

Publicado por Brisa
hace 5 meses

¡Hola a todos!

Estoy teniendo problemas para manejar correctamente las referencias mutables en Rust al hacer una llamada recursiva a una función. Me gustaría que alguien me ayudara a entender el error de "borrowing" que me aparece y cómo solucionarlo.

Aquí está mi código:

fn main() {
    let mut vector = vec![1, 2, 3, 4, 5];
    modificar_vector(&mut vector, 0);
    println!("El vector modificado es: {:?}", vector);
}

fn modificar_vector(vector: &mut Vec<i32>, indice: usize) {
    if indice >= vector.len() {
        return;
    }

    vector[indice] *= 2;
    modificar_vector(vector, indice + 1);
}

Cuando trato de compilar este código, obtengo el siguiente error:

error[E0499]: cannot borrow `*vector` as mutable more than once at a time
 --> src/main.rs:11:17
  |
9 |     vector[indice] *= 2;
  |     - first mutable borrow occurs here
10 |     modificar_vector(vector, indice + 1);
  |                      ------ first borrow later used here
11 | }
  |   ^ second mutable borrow occurs here

error: aborting due to previous error

For more information about this error, try `rustc --explain E0499`.
error: could not compile `playground`

To learn more, run the command again with --verbose.

¡Entiendo que el error tiene que ver con el manejo de referencias mutables, pero no sé cómo solucionarlo! Agradezco cualquier ayuda o explicación que puedan brindarme.

¡Gracias!

rust mutable
Respuesta de Gordon Shumway
hace 5 meses

¡Hola Brisa!

El error que estás encontrando se debe a una de las reglas fundamentales del sistema de préstamos de Rust: no puedes tener más de una referencia mutable al mismo dato en un determinado ámbito (scope). En tu caso, intentas crear una nueva referencia mutable al mismo vector dentro de una función que ya tiene una referencia mutable al mismo vector.

Tu función modificar_vector se llama a sí misma con una referencia mutable al mismo vector (vector), lo que viola esa regla porque al momento de llamar a la función recursivamente, la referencia mutable original todavía está activa.

Para solucionar este problema, puedes hacer que la llamada recursiva sea la última operación en tu función para que Rust pueda reutilizar la referencia mutable sin problema. Esto se conoce como tail recursion. Aquí te dejo cómo quedaría el código corregido:

fn main() {
    let mut vector = vec![1, 2, 3, 4, 5];
    modificar_vector(&mut vector, 0);
    println!("El vector modificado es: {:?}", vector);
}

fn modificar_vector(vector: &mut Vec<i32>, indice: usize) {
    if indice >= vector.len() {
        return;
    }

    vector[indice] *= 2;

    // Recursión al final - tail recursion
    if indice + 1 < vector.len() {
        modificar_vector(vector, indice + 1);
    }
}

Haciendo la verificación if indice + 1 < vector.len() antes de llamar a la recursión, nos aseguramos de que no hay ninguna otra operación pendiente con la referencia mutable, por lo que Rust puede reutilizarla sin problemas.

Intenta de nuevo con este enfoque y debería funcionar sin errores. ¡Espero que esto te ayude a entender mejor como funciona el sistema de préstamos de Rust!