Clarification with regards to `mut` array

I have some doubt whether the following is an expected behavior:

fn main() {
    let mut month_1 = String::from_str("Jan");
    let mut month_2 = String::from_str("Feb");
    let mut month_3 = String::from_str("Mar");

    let months = [&mut month_1, &mut month_2, &mut month_3];
    println!("{:?}", months);

    *months[0] = String::from_str("Apr");
    println!("{:?}", months);
}

This produces the following output:

[Ok("Jan"), Ok("Feb"), Ok("Mar")]
[Ok("Apr"), Ok("Feb"), Ok("Mar")]

My confusion is even though the array months is not mut, it allows us to modify the actual data contained as a mutable reference.

Is this behavior expected ?

Thanks in advance.

Yes, it is. No element of the array is being modified, only its referent.

let vs let mut determines whether you can modify the data stored within a particular variable binding.

In this case, you're not actually modifying the data stored within months, you're just accessing one of the mutable references contained within. The data you're mutating is stored within month_1, which is defined as mutable, so the compiler is happy.

Compare this with if you tried to actually reassign one of the elements:

fn main() {
    let mut month_1 = String::from_str("Jan");
    let mut month_2 = String::from_str("Feb");
    let mut month_3 = String::from_str("Mar");

    let months = [&mut month_1, &mut month_2, &mut month_3];
    println!("{:?}", months);

    let mut month_4 = String::from_str("Apr");
    months[0] = &mut month_4;
    println!("{:?}", months);
}

In that example, you would be changing what's stored in months, and the compiler would error:

rror[E0594]: cannot assign to `months[_]`, as `months` is not declared as mutable
  --> src/main.rs:12:5
   |
8  |     let months = [&mut month_1, &mut month_2, &mut month_3];
   |         ------ help: consider changing this to be mutable: `mut months`
...
12 |     months[0] = &mut month_4;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^ cannot assign
1 Like