Avoid fighting the borrow checker by designing your code to minimize mutable borrows and prefer immutable references where possible. Use &T for reading data, &mut T only when strictly necessary, and consider smart pointers like Rc<T> or RefCell<T> for complex ownership scenarios.
fn main() {
let mut numbers = vec![1, 2, 3];
let first = &numbers[0]; // Immutable borrow
println!("First: {first}");
numbers.push(4); // Mutable borrow after immutable one ends
}
For cases requiring multiple owners or interior mutability:
use std::rc::Rc;
use std::cell::RefCell;
fn main() {
let data = Rc::new(RefCell::new(vec![1, 2, 3]));
let clone = Rc::clone(&data);
data.borrow_mut().push(4); // Interior mutability
println!("Data: {:?}", clone.borrow());
}