Checkout the Rust code below. It compiles
fn main() {
let vec0 = Vec::new();
let mut vec1 = fill_vec(vec0);
println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1);
vec1.push(88);
println!("{} has length {} content `{:?}`", "vec1", vec1.len(), vec1);
}
fn fill_vec(mut vec: Vec<i32>) -> Vec<i32> {
vec.push(22);
vec.push(44);
vec.push(66);
vec
}
Here I am declaring vec0 as immutable but fill_vec takes in a mutable vector. Depending on the function signature it seems Rust is changing the nature of the argument being passed.
My question is, this obviously seems like a "shot yourself in the foot" instant. Why does Rust allow this? Or, is this actually safe and I am missing something?
There are different things at play here that can all explain why this behavior make sense:
First of, mut doesn't really mean "mutable". There are such things as interior mutability, Cells, Mutexes, etc., which allow you to modify state without needing a single mut. Rather, mut means that you can get mutually exclusive references.
Second, mutability is a property of a binding. vec0 in main and vec in fill_vec are different bindings, so they can have different mutability.
See also:
Finally ownership: fill_vec takes full ownership of its parameter, which effectively doesn't exist anymore in main. Why should the function not be allowed to do whatever it wants with its owned parameters? Had the function taken the parameter as a mutable reference, you would have needed to declare the original binding as mut:
fn main() {
let mut vec0 = Vec::new();
// ^^^ now _needs_ a mutable binding
fill_vec(&mut vec0);
// ^^^^ needs an explicit `&mut` reference
}
fn fill_vec(vec: &mut Vec<i32>) {
// ^^^^ borrows rather than take ownership
// …
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With