Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Immutable object changing to mutable depending on function signature

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?

like image 835
Rajarshi Maitra Avatar asked Jul 03 '26 06:07

Rajarshi Maitra


1 Answers

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:

    • What does 'let x = x' do in Rust?
  • 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
        // …
    }
    
like image 77
mcarton Avatar answered Jul 05 '26 00:07

mcarton



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!