&self is an immutable reference to the instance — read-only access. &mut self is a mutable reference — read-write access, but exclusive (no other references allowed while it exists).
&self — immutable borrow:
1struct TodoList {2 items: Vec<String>,3}45impl TodoList {6 fn count(&self) -> usize {7 self.items.len()8 }910 fn is_empty(&self) -> bool {11 self.items.is_empty()12 }1314 fn contains(&self, item: &str) -> bool {15 self.items.iter().any(|i| i == item)16 }17}1819let list = TodoList { items: vec!["Buy milk".into()] };20println!("Count: {}", list.count()); // 121println!("Has milk: {}", list.contains("Buy milk")); // true
&mut self — mutable borrow:
1impl TodoList {2 fn add(&mut self, item: String) {3 self.items.push(item);4 }56 fn remove(&mut self, index: usize) -> Option<String> {7 if index < self.items.len() {8 Some(self.items.remove(index))9 } else {10 None11 }12 }1314 fn clear(&mut self) {15 self.items.clear();16 }17}1819let mut list = TodoList { items: vec![] };20list.add("Learn Rust".into());21list.add("Build project".into());22list.remove(0);
When to use &self:
When to use &mut self:
Common mistakes:
let mut when calling &mut self methods.