3

I'm trying to understand ownership in Rust and faced a misunderstanding related to transfer ownership. Consider the following code:

fn main() {
    let closure = || 32;
    foo(closure);
    foo(closure); //perfectly fine
}

fn foo<F>(f: F) -> u32
where
    F: Fn() -> u32,
{
    f()
}

playground

I thought that the ownership should be transferred and the second call foo(closure) should not be allowed.

Why does it work?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Some Name
  • 8,555
  • 5
  • 27
  • 77

1 Answers1

6

Your closure implements Copy, so when you use it a second time, a copy is automatically made. Your code works for the same reason this does:

fn main() {
    let v = 32;
    foo(v);
    foo(v);
}

fn foo(a: u32) -> u32 {
    a
}

See also:

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • Thanks for the point. Indeed the behavior is well-specified in the [reference](https://doc.rust-lang.org/reference/types/closure.html#other-traits): _A closure is `Clone` or `Copy` if it does not capture any values by unique immutable or mutable reference, and if all values it captures by copy or move are `Clone` or `Copy`, respectively._ – Some Name Jul 27 '20 at 17:20
  • This is kind of offtopic for that specific question, but I'd like to clarify one point regarding captured closure. Assuming a closure captures some variable and take ownership of it with `move` specified before the argument list. If the reference to the variable is used in the closure's body will the lifetime of the captured variable be the same as the closure's one and the closure will be the `Fn`, not `FnOnce`? – Some Name Jul 27 '20 at 17:28
  • 1
    @SomeName `move` and what traits are implemented are two separate concepts. See [When does a closure implement Fn, FnMut and FnOnce?](https://stackoverflow.com/q/30177395/155423). For the lifetime question, see [Why can't I store a value and a reference to that value in the same struct?](https://stackoverflow.com/a/32300133/155423), specifically the paragraph starting with "A lifetime is a bit of metadata " – Shepmaster Jul 27 '20 at 17:44