Mut modifier silently changing type?

I have the following code:

    let mut vec = vec![(1, 1), (2, 2), (3, 3), (4, 4)];
    vec.iter_mut().for_each(|(mut x, _y)| { x += 1 });
    println!("{vec:?}");
    
    // Just for reference: what the code originally set out to do, but missed because of copy and past from a line that included the `mut` above.
    vec.iter_mut().for_each(|(x, _y)| { *x += 1 });
    println!("{vec:?}");

(playground)

Intuitively (at least as per my intuition...), the first iteration shouldn't compile: we are adding something to x, but x should be a mutable reference. And lo and behold, if I remove the mut modifier in line 2 I get an error:

3 |     vec.iter_mut().for_each(|(x, _y)| { x += 1 });
  |                                         -^^^^^
  |                                         |
  |                                         cannot use `+=` on type `&mut {integer}`

So...just adding the mut keyword there apparently changes the type of x from a mutable reference to an integer to a mere integer?

That seems like a rather large foot gun to me and I am struggling to classify it as anything but a bug. Is there some rationale to it or is it an actual issue?

It's match ergonomics, I think.

It is, indeed. There's an open issue for this.

3 Likes

impl AddAssign<i32> for &mut i32 does not exist.
however, it does exist for i32.

you should dereference it, as the compiler tells you :slight_smile:

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.