W Rust istnieją dwa podstawowe rodzaje odniesień:
&T): zapewniają dostęp tylko do odczytu.&mut T): pozwalają na modyfikację wartości, do której się odnosi.Zasady:
Przykłady składni:
fn read(val: &i32) { println!("{}", val); } fn write(val: &mut i32) { *val += 1; } let mut x = 5; read(&x); write(&mut x);
Pytanie: Czy można utworzyć dwa mutowalne odniesienia do jednej zmiennej w różnych zakresach widoczności tej samej funkcji?
Odpowiedź: Nie, nawet jeśli odniesienia są tworzone w różnych blokach, zakres widoczności do analizy pożyczek obejmuje całą funkcję lub zmienną, jeśli kompilator nie może dokładnie udowodnić, że odniesienia się nie krzyżują. Często prowadzi to do błędów kompilacji:
let mut x = 10; let r1 = &mut x; { let r2 = &mut x; // błąd! }
Historia
W trakcie rozwoju parsera, programista próbował jednocześnie przechowywać mutowalne i niemutowalne odniesienie do jednego bufora w celu optymalizacji odczytu i zapisu. W rezultacie kod nie kompilował się, a po "obejściu" reguły przez unsafe pojawiły się błędy wycieku danych.
Historia
Na początku projektu przetwarzania danych jeden z uczestników nie robił "reanalyze borrow checker" dla skomplikowanego kodu z zagnieżdżonymi zakresami. W rezultacie z powodu krzyżujących się odniesień pojawił się klasyczny błąd "cannot borrow as mutable because it's also borrowed as immutable" bez wyraźnego wskazania w kodzie źródłowym miejsca problemu.
Historia
W kodzie wielowątkowym używano zwykłych odniesień do dostępu do współdzielonych danych. Przy próbie zmiany danych w równoległych wątkach występowały niespodziewane błędy kompilatora i wyścigi danych przy obejściu borrow checkera przez niebezpieczny kod.