1

The Rust Programming Language says:

If you want to force the closure to take ownership of the values it uses in the environment, you can use the move keyword before the parameter list

What I have noticed with my code is that it won't take ownership of these values. The differences between my code and the given example are:

  • using an integer instead of a Vec
  • making x mutable instead of immutable

Example 1: The Rust Programming Language

fn main() {
    let x = vec![1, 2, 3];

    let equal_to_x = move |z| z == x;

    println!("can't use x here: {:?}", x);

    let y = vec![1, 2, 3];

    assert!(equal_to_x(y));
}

Example 2: My Code

fn main() {
    let mut x = 1;

    let equal_to_x = move |z| z == x;

    println!("can use x here: {:?}", x);

    let y = 1;

    assert!(equal_to_x(y));
}
  1. Why will example 2 compile but example 1 won't?

  2. AWhy is the ownership of x not moved even if I explicitly write move in front of the closure? Why is x accessible after moving it into the closure?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366

1 Answers1

5

The answer is given in the error message of your first example

error[E0382]: borrow of moved value: `x`
 --> src/main.rs:6:40
  |
2 |     let x = vec![1, 2, 3];
  |         - move occurs because `x` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
3 | 
4 |     let equal_to_x = move |z| z == x;
  |                      --------      - variable moved due to use in closure
  |                      |
  |                      value moved into closure here
5 | 
6 |     println!("can't use x here: {:?}", x);
  |                                        ^ value borrowed here after move

"move occurs because x has type std::vec::Vec<i32>, which does not implement the Copy trait"

This means, when a type implements the Copy trait (like an i32 does), move copies the variable into the scope of the closure.

hellow
  • 12,430
  • 7
  • 56
  • 79
  • Thanks for your answer! Does it make any difference if I remove the `move`? It will compile as well. – Marius Rodi May 10 '19 at 12:21
  • For copy types it won't make any difference at all. – hellow May 10 '19 at 12:22
  • 3
    @MariusRodi It does make a difference whether you use `move`, even for types that are `Copy`. Without `move`, the variable will be borrowed, possibly mutably, and with `move` it will be copied into the closure. In the former case, there is only one variable with a single value that is borrowed by the closure, while in the second case there are two completely separate variables – one inside the closure and one in the enclosing scope. – Sven Marnach May 10 '19 at 14:12
  • See also [How to copy instead of borrow an i64 into a closure in Rust?](https://stackoverflow.com/q/54287719/155423); [How to force a move of a type which implements the Copy trait?](https://stackoverflow.com/q/31168589/155423) – Shepmaster May 10 '19 at 21:07
  • This should be the accepted answer since the reason is appropriately explained here. – Arko Nov 19 '22 at 03:08