8

Example code:

fn main() {
    let a = [1, 2, 3, 4, 5];
    reset(a);
}

fn reset(mut b: [u32; 5]) {
    b[0] = 5;
}

The variable a is an immutable array, and the reset function's parameter b is a mutable array; intuitively I need to modify a to a mutable array before I can call the reset method, but the compiler tells me that I don't need to do this, why is this?

fn main() {
    let mut a = [1, 2, 3, 4, 5];
    reset(a);
}

fn reset(mut b: [u32; 5]) {
    b[0] = 5;
}
warning: variable does not need to be mutable
 --> src/main.rs:2:9
  |
2 |     let mut a = [1, 2, 3, 4, 5];
  |         ----^
  |         |
  |         help: remove this `mut`
  |
  = note: #[warn(unused_mut)] on by default
Peter Hall
  • 53,120
  • 14
  • 139
  • 204
iDuanYingJie
  • 663
  • 4
  • 11

1 Answers1

11

When you pass by value, you are transferring ownership of the value. No copies of the variable are required — first main owns it, then reset owns it, then it's gone1.

In Rust, when you have ownership of a variable, you can control the mutability of it. For example, you can do this:

let a = [1, 2, 3, 4, 5];
let mut b = a;

You could also do the same thing inside of reset, although I would not do this, preferring to use the mut in the function signature:

fn reset(b: [u32; 5]) {
    let mut c = b;
    c[0] = 5;
}

See also:


1 — In this specific case, your type is an [i32; 5], which implements the Copy trait. If you attempted to use a after giving ownership to reset, then an implicit copy would be made. The value of a would appear unchanged.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • So, variables a and b point to different memory addresses, right? – iDuanYingJie Jan 10 '19 at 02:28
  • 1
    @iDuanYingJie they might, but they don't have to. In your example code, the optimizer can see that `a` isn't used after it's passed to `reset`, so it might as well just use the same memory chunk for `b`. (It's tricky to tell because this code is probably optimized to a no-op because it doesn't do anything). – Shepmaster Jan 10 '19 at 02:30
  • oh, yes! if a is uesd after it's passed to reset, i think this is equivalent to let mut b = memcpy(a); right? – iDuanYingJie Jan 10 '19 at 02:37
  • @iDuanYingJie Yes, *if* `a` is used after `reset`, then a copy of `a` would be created and one passed to `reset` the other remaining in `main`. – Shepmaster Jan 10 '19 at 02:40