RefCell::borrow în Rust

borrow() împrumută valoarea din RefCell pentru citire, borrow_mut() pentru scriere; conflictele dau panică.

Sintaxă
fn borrow(&self) -> Ref<'_, T>
fn borrow_mut(&self) -> RefMut<'_, T>

Ce face RefCell::borrow

borrow() returnează un Ref<T>, care se comportă ca &T. Pot exista oricâte Ref-uri în același timp. borrow_mut() returnează un RefMut<T>, care se comportă ca &mut T; poate exista doar unul și niciun Ref în paralel.

RefCell ține un contor al împrumuturilor active. Când variabila Ref/RefMut dispare (la sfârșitul blocului sau al expresiei), contorul scade. Un apel care ar încălca regula intră în panică cu RefCell already borrowed sau RefCell already mutably borrowed.

Ce returnează

Ref<'_, T>, respectiv RefMut<'_, T>.

Exemple

Exemplul 1: Mai mulți cititori în același timp

use std::cell::RefCell;

fn main() {
    let oras = RefCell::new(String::from("Iași"));

    let a = oras.borrow();
    let b = oras.borrow();
    println!("a = {a}, b = {b}, lungime = {}", a.len());
    drop(a);
    drop(b);

    oras.borrow_mut().push_str(" (capitala Moldovei)");
    println!("{}", oras.borrow());
}

Rezultat

a = Iași, b = Iași, lungime = 5
Iași (capitala Moldovei)

Exemplul 2: Panica la două împrumuturi de scriere

primul ține împrumutul de scriere până la finalul lui main, așa că al doilea borrow_mut intră în panică.

use std::cell::RefCell;

fn main() {
    let scor = RefCell::new(0);
    let mut primul = scor.borrow_mut();
    let mut al_doilea = scor.borrow_mut();
    *primul += 1;
    *al_doilea += 1;
}

Rezultat (programul se oprește cu panică, codul de ieșire 101)


thread 'main' (61277) panicked at src/main.rs:6:30:
RefCell already borrowed
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Greșeli frecvente

  • Scrii let v = celula.borrow_mut(); functie(&celula);, iar functie face borrow(): panică. Eliberează împrumutul înainte de apel.
  • Folosești if let sau match pe celula.borrow() și modifici celula în ramuri: împrumutul ține pe toată durata construcției.

Comenzi înrudite

  • RefCell: Permite modificarea unei valori prin referință comună (&), verificând regulile de împrumut la rulare, nu la compilare.
  • Cell: Celulă cu mutabilitate interioară pentru valori Copy: get() copiază valoarea afară, set() pune una nouă, prin &self.
  • mem::drop: Distruge o valoare imediat, înainte de sfârșitul blocului: eliberează memoria, închide fișierul, deblochează mutex-ul.