Borrowing (Ausleihen) in Rust ist ein Mechanismus, um eine Variable vorübergehend über Referenzen "zu leihen". Rust unterscheidet zwischen unveränderlichem Borrowing (&T) und veränderlichem Borrowing (&mut T). Es können beliebig viele unveränderliche Referenzen gleichzeitig existieren, aber nur eine veränderliche. Es ist nicht erlaubt, gleichzeitig veränderliche und unveränderliche Referenzen auf dasselbe Objekt zu haben.
Diese Regel gewährleistet, dass es keine Datenrennen zur Compile-Zeit gibt und macht Rust sicher für die nebenläufige Programmierung.
Beispiel:
let mut value = 5; let r1 = &value; let r2 = &value; // let r3 = &mut value; // FEHLER: &mut kann nicht erstellt werden, solange es ein & gibt println!("{} {}", r1, r2); // r3 ist bis zum Ende des Gültigkeitsbereichs von r1/r2 verboten
Frage: Kann man in einem Gültigkeitsbereich eine &mut Referenz und beliebig viele & Referenzen auf dasselbe Objekt erstellen?
Typische falsche Antwort: Ja, aber nur, wenn sie sich in Bezug auf die Lebensdauer nicht überschneiden.
Richtige Antwort: Gleichzeitig kann es keine veränderliche und unveränderliche Referenz auf dasselbe Objekt geben (selbst wenn ihre Zugriffe sich statisch im Code nicht überschneiden), solange eine lebt — sind andere verboten. Die Sicherheit überprüft der Borrow Checker.
Beispiel:
let mut x = 10; let y = &x; let z = &mut x; // Fehler, y ist noch im Gültigkeitsbereich println!("{}", y); // y wird später benötigt
Geschichte
In einem großen Projekt mit paralleler Datenverarbeitung entschloss sich ein Entwickler, unveränderliche Referenzen auf einen Vektor zu verwenden und versuchte dann, eine veränderliche Referenz zum Sortieren zu erhalten. Der Code funktionierte im Test, konnte aber nach der Umstrukturierung nicht mehr kompiliert werden, da die Lebensdauer der unveränderlichen Referenzen verlängert wurde.
Geschichte
In einem internen Dienst wurde eine Struktur über &mut geändert, während die Referenzen auf Felder für die spätere Übertragung in einen anderen Thread gespeichert wurden. Es trat ein Datenrennen und ein Absturz auf, weil die Borrow-Regeln nicht eingehalten wurden — Rust schützt nur zur Compile-Zeit davor, aber die Fehler lagen in unsafe-Blöcken, wo die Garantien aufgehoben sind.
Geschichte
Unzureichende Dokumentation der API: Die Bibliothek akzeptierte gleichzeitig & und &mut für verschiedene Felder der Struktur, aber aufgrund von Aliasing wurde die Invarianz verletzt und es traten schwer fassbare Bugs mit Diensten auf, die diese Bibliothek integrierten.