The Rust borrow checker enforces memory safety by ensuring that at any given time, you have either one mutable reference or any number of immutable references to a value, but never both. This prevents data races and use-after-free errors at compile time without needing a garbage collector.
let mut s = String::from("hello");
let r1 = &s; // Immutable borrow
let r2 = &s; // Immutable borrow allowed
// let r3 = &mut s; // ERROR: Cannot borrow `s` as mutable while it is also borrowed as immutable
println!("{r1}, {r2}"); // Borrow ends here
let r3 = &mut s; // Mutable borrow now allowed
r3.push_str(", world");
The borrow checker tracks the lifetime of references to ensure they do not outlive the data they point to and that mutable and immutable borrows do not overlap.