Rust error E0596: cannot borrow as mutable, as it is not declared as mutable
Fix Rust's E0596 error: add mut to the variable, take &mut in the function signature, or make a mutating closure mut.
E0596 means you tried to change something through a path that doesn't allow changes. In Rust, mutability is opt-in at every level: the variable must be let mut, and a reference must be &mut to be written through. The fix is to add mut in the right place, and rustc's help: line usually shows exactly where.
Case 1: the variable isn't mut
fn main() {
let names = Vec::new();
names.push("Ferris");
println!("{names:?}");
}
error[E0596]: cannot borrow `names` as mutable, as it is not declared as mutable
--> src/main.rs:3:5
|
3 | names.push("Ferris");
| ^^^^^ cannot borrow as mutable
|
help: consider changing this to be mutable
|
2 | let mut names = Vec::new();
| +++
push takes &mut self, so calling it borrows names mutably. Write let mut names. The same applies to read_line(&mut line), sort(), insert, clear and every other method that changes its receiver.
Case 2: the parameter is & but the function modifies it
fn add_guest(list: &Vec<String>, name: &str) {
list.push(name.to_string());
}
fn main() {
let mut guests = Vec::new();
add_guest(&guests, "Ferris");
println!("{guests:?}");
}
error[E0596]: cannot borrow `*list` as mutable, as it is behind a `&` reference
A shared reference is read-only, no matter whether the original variable is mut. Change the signature to list: &mut Vec<String> and the call to add_guest(&mut guests, "Ferris"). Both sides must say mut: that's how readers of the call site know the function can change guests.
Case 3: a method takes &self but changes a field
Inside fn record(&self), self.hits += 1 fails with the closely related E0594, "cannot assign to self.hits, which is behind a & reference". Change the method to &mut self, and make the variable you call it on let mut. (If the method genuinely must stay &self, for example a cache inside a shared object, that's what Cell, RefCell and Mutex are for: interior mutability.)
Case 4: a closure that mutates a capture
fn main() {
let mut count = 0;
let bump = || count += 1;
bump();
println!("{count}");
}
error[E0596]: cannot borrow `bump` as mutable, as it is not declared as mutable
A closure that changes a captured variable is an FnMut, and calling it needs a mutable borrow of the closure itself: write let mut bump = || count += 1;.
Case 5: data inside Rc or behind an iterator
Rc<T>only gives shared access:shared.push(3)on anRc<Vec<i32>>is "cannot borrow data in anRcas mutable". UseRc<RefCell<T>>for shared mutable data (orArc<Mutex<T>>across threads).for x in &v { *x += 1; }is E0594. Iterate with&mut v(orv.iter_mut()) to get&mutelements.
Don't over-correct
Adding mut where nothing changes produces the warning variable does not need to be mutable. The goal is that every mut in your code marks a place where something really changes.
Example
struct Counter {
hits: u32,
}
impl Counter {
fn record(&mut self) {
self.hits += 1;
}
}
fn add_guest(list: &mut Vec<String>, name: &str) {
list.push(name.to_string());
}
fn main() {
let mut names = Vec::new();
names.push("Ferris");
println!("{names:?}");
let mut guests = Vec::new();
add_guest(&mut guests, "Ferris");
add_guest(&mut guests, "Corro");
println!("{guests:?}");
let mut counter = Counter { hits: 0 };
counter.record();
counter.record();
println!("hits {}", counter.hits);
let mut count = 0;
let mut bump = || count += 1;
bump();
bump();
println!("count {count}");
let mut levels = vec![1, 2, 3];
for lvl in &mut levels {
*lvl *= 10;
}
println!("{levels:?}");
}
Output:
["Ferris"]
["Ferris", "Corro"]
hits 2
count 2
[10, 20, 30]