Verificação de Empréstimo

O verificador de empréstimo (borrow checker) do Rust impõe restrições sobre as maneiras como você pode emprestar valores. Para um determinado valor, a qualquer momento:

  • Você pode ter uma ou mais referências compartilhadas para o valor, ou
  • Você pode ter exatamente uma referência exclusiva para o valor.
fn main() {
    let mut a: i32 = 10;
    let b: &i32 = &a;

    {
        let c: &mut i32 = &mut a;
        *c = 20;
    }

    println!("a: {a}");
    println!("b: {b}");
}
This slide should take about 10 minutes.
  • Observe que o requisito é que as referências conflitantes não existam no mesmo ponto. Não importa onde a referência é desreferenciada.
  • O código acima não compila porque a é emprestado como mutável (através de c) e como imutável (através de b) ao mesmo tempo.
  • Mova a instrução println! para b antes do escopo que introduz c para fazer o código compilar.
  • Após essa alteração, o compilador percebe que b só é usado antes do novo empréstimo mutável de a através de c. Este é um recurso do verificador de empréstimo (borrow checker) chamado “tempos de vida não lexicais”.
  • A restrição de referência exclusiva é bastante forte. O Rust a usa para que data races (corridas de dados) não ocorram. O Rust também depende dessa restrição para otimizar o código. Por exemplo, um valor atrás de uma referência compartilhada pode ser armazenado com segurança em um registrador pelo tempo de vida dessa referência.
  • O verificador de empréstimo (borrow checker) é projetado para acomodar muitos padrões comuns, como obter referências exclusivas para campos diferentes em uma struct ao mesmo tempo. Mas, há algumas situações em que ele não entende muito bem e isso geralmente resulta em “lutar com o verificador de empréstimo”.