AnyCompiler

Referencias y Borrowing

Una referencia te permite usar un valor sin tomar su ownership — se escribe con &. El dueño original conserva el valor, y la referencia solo toma prestado (borrow) el acceso a él temporalmente.

fn main() {
    let s1 = String::from("hello");
    let len = calculate_length(&s1);

    println!("The length of '{}' is {}.", s1, len);
}

fn calculate_length(s: &String) -> usize {
    s.len()
}
Output
The length of 'hello' is 5.

calculate_length toma prestado s1 a través de una referencia en vez de tomar su ownership, así que s1 sigue siendo perfectamente usable de vuelta en main después de la llamada.

Referencias mutables

Una referencia mutable, &mut T, permite que una función modifique el valor que toma prestado. Rust permite esto, pero con una restricción crucial: puedes tener o bien una referencia mutable, o cualquier número de referencias inmutables, a un valor a la vez — nunca ambas.

fn main() {
    let mut s = String::from("hello");
    change(&mut s);
    println!("{}", s);
}

fn change(s: &mut String) {
    s.push_str(", world");
}
Output
hello, world

Cómo se ve un conflicto de borrow real

Esto es genuinamente lo que reporta rustc cuando intentas crear una referencia mutable mientras una inmutable todavía está en uso — capturado de una ejecución real, no escrito para parecer plausible:

fn main() {
    let mut s = String::from("hello");

    let r1 = &s;
    let r2 = &mut s;

    println!("{}, {}", r1, r2);
}
Output
error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immutable
 --> main.rs:5:14
  |
4 |     let r1 = &s;
  |              -- immutable borrow occurs here
5 |     let r2 = &mut s;
  |              ^^^^^^ mutable borrow occurs here
6 | 
7 |     println!("{}, {}", r1, r2);
  |                        -- immutable borrow later used here

error: aborting due to previous error

For more information about this error, try `rustc --explain E0502`.

Esta regla es lo que descarta por completo las data races, en tiempo de compilación — dos partes de un programa nunca pueden terminar leyendo y escribiendo los mismos datos a la vez, porque el compilador simplemente no dejará que compile el código que lo permitiría.

Siguiente: strings y slices — la diferencia entre un String con ownership y un &str prestado (borrowed).

Practice Exercise

Escribe una función word_count(s: &String) -> usize que devuelva el número de palabras en s usando s.split_whitespace().count(). Llámala con una referencia a un String que contenga "the quick brown fox" e imprime el resultado.