Reference to the vector member

Why the following code does not work and how to fix it?

fn main() {
    let mut v = [1, 2, 3, 4, 5];
    let mut e = &v[2];
    
    e = 7;

    println!("{:?}", v);
}

Hello there,

If you are trying to do what I think you are trying to do, the code does not work, because e is set as a simple reference to the 3rd element of the slice v.

Instead, e needs to hold a mutable reference to the 3rd element of the slice v. Also, note that it is not e you are mutating, it is a element in v. So, e does not need to be mutable.

fn main() {
    let mut v = [1, 2, 3, 4, 5];
    let e = &mut v[2];
    
    *e = 7;

    println!("{:?}", v);
}

Hope this helps

1 Like

Please, fix my code. The result has to be [1, 2, 7, 4, 5].

They did, and it is. (The code is pedagogically blurred to encourage you to apply the explanation yourself.) Have you tried running it in the Playground?

2 Likes

Building the original code on the playground gives the following error:

error[E0308]: mismatched types
 --> src/main.rs:5:9
  |
3 |     let mut e = &v[2];
  |                 ----- expected due to this value
4 |     
5 |     e = 7;
  |         ^
  |         |
  |         expected `&{integer}`, found integer
  |         help: consider borrowing here: `&7`

This is a rather poor hint, I have to say, but what it's saying is that "if you want to change e to point to a 7, then you should borrow the 7 first".

Instead, you want to change what e points to, this needs a dereference, by changing the line to *e = 7; (note the addition of the * to refer to what e points at). That would give the the following, much more helpful messages:

warning: variable does not need to be mutable
 --> src/main.rs:2:9
  |
2 |     let mut v = [1, 2, 3, 4, 5];
  |         ----^
  |         |
  |         help: remove this `mut`
  |
  = note: `#[warn(unused_mut)]` on by default

warning: variable does not need to be mutable
 --> src/main.rs:3:9
  |
3 |     let mut e = &v[2];
  |         ----^
  |         |
  |         help: remove this `mut`

error[E0594]: cannot assign to `*e`, which is behind a `&` reference
 --> src/main.rs:5:5
  |
3 |     let mut e = &v[2];
  |                 ----- help: consider changing this to be a mutable reference: `&mut v[2]`
4 |     
5 |     *e = 7;
  |     ^^^^^^ `e` is a `&` reference, so the data it refers to cannot be written

For now, the important one is the last one, which tells you exactly what you want to do. The first warning, that you don't need a mut on v because you never mutate it will go away when you do, and the second one is also correct: you don't mutate e, only *e, what it points at.

1 Like

Similarly, keeping the e = 7 but changing it to &mut v[2] also gives a useful error message:

error[E0308]: mismatched types
 --> src/main.rs:5:9
  |
3 |     let mut e = &mut v[2];
  |                 --------- expected due to this value
4 |     
5 |     e = 7;
  |         ^ expected `&mut {integer}`, found integer
  |
help: consider dereferencing here to assign to the mutably borrowed value
  |
5 |     *e = 7;
  |     +

It's the combination of assigning to e and using an immutable reference that makes the code so significantly different from what is actually wanted here that the compiler heuristics produce “help:” hints (about changing it to &7) moving the code further into the wrong direction.

3 Likes

Thank you a lot.

I read just errors form eclipse without compiling. After compiling I have more detailed error report.