The Key Insight: Rust's borrow checker tracks the last actual use of a reference, not when it goes out of scope.
Before NLL (The Old Pain)
let chef = &mut kitchen;
chef.push("sugar");
println!("Chef's kitchen: {:?}", chef);
let inspector = &kitchen; // ❌ ERROR in old Rust
println!("Inspector: {:?}", inspector);
// chef scope ends here
Problem: Had to create artificial scopes just to end borrows early.
After NLL (The Modern Magic)
let chef = &mut kitchen;
chef.push("sugar");
println!("Chef's kitchen: {:?}", chef); // ← Last use ends borrow
let inspector = &kitchen; // ✅ Safe!
println!("Inspector: {:?}", inspector);
Solution: Borrow ends when you stop using it, not when scope ends.
Why This Matters
fn smart_processing() {
let mut data = vec![1, 2, 3];
// Modification phase
let modifier = &mut data;
modifier.push(4);
println!("Modified: {:?}", modifier); // Last use = borrow ends
// Reading phase (no extra scopes needed!)
let reader1 = &data; // ✅ Works immediately
let reader2 = &data; // ✅ Multiple readers fine
println!("Readers see: {:?} and {:?}", reader1, reader2);
}
Result: Rust feels natural while staying memory-safe. The borrow checker became your helpful assistant instead of a strict teacher.
Top comments (0)