AnyCompiler

Referências e Borrowing

Uma referência permite usar um valor sem tomar seu ownership — escrita com &. O dono original mantém o valor, e a referência apenas toma emprestado (borrow) o acesso a ele temporariamente.

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 emprestado s1 através de uma referência em vez de tomar seu ownership, então s1 continua perfeitamente usável de volta em main depois da chamada.

Referências mutáveis

Uma referência mutável, &mut T, permite que uma função modifique o valor que ela toma emprestado. O Rust permite isso, mas com uma restrição crucial: você pode ter ou uma referência mutável, ou qualquer número de referências imutáveis, a um valor por 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

Como é um conflito de borrow real

Isto é genuinamente o que o rustc reporta quando você tenta criar uma referência mutável enquanto uma imutável ainda está em uso — capturado de uma execução real, não escrito para parecer plausível:

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`.

Essa regra é o que descarta data races por completo, em tempo de compilação — duas partes de um programa nunca podem acabar lendo e escrevendo os mesmos dados ao mesmo tempo, porque o compilador simplesmente não deixa compilar o código que permitiria isso.

Próximo: strings e slices — a diferença entre um String com ownership e um &str emprestado (borrowed).

Practice Exercise

Escreva uma função word_count(s: &String) -> usize que retorne o número de palavras em s usando s.split_whitespace().count(). Chame-a com uma referência a um String contendo "the quick brown fox" e imprima o resultado.