Limiting what can be moved

Is there anyway to get the compiler / linter to enforce the following pattern:

{ // move start

  let x = ..;
  let y = ...;
  
  move | ... | { ... }



} // move end

Then, the move is only allowed to move things within the move begin / move end block. The goal here is that I want to be explicit about what is being moved.

2 Likes

By default all values are moved. Exceptions are, when its type implement Copy.

Ref: https://doc.rust-lang.org/1.27.0/reference/expressions.html#moved-and-copied-types

To be pedantic, I think it is "all values USED IN THE CLOSURE are moved"

Sometimes, in large functions, it is hard to see what is / is not moved.

This I want to put a {} block around a move and somehow have the linter / compiler tell me if something else is being moved. Is there a way to lint for this?

1 Like

Rust doesn't have any features for listing the captured variables. You can stop things from moving by using them after the closure, possibly in a let a = a or drop(a) way.

1 Like

Yes you can be explicit it is just a matter of adding:

fn foo() { // move start

  let x = ..;
  let y = ...;
  
  move | ... | { ... }

} // move end

I am kidding of course, if only slightly. If you are concerned about what is moved thats probably because there is too much complexity therefore the extra function boundary might be a good idea.

1 Like
{
    fn closure(x: T, y: U) -> impl Fn(...) -> ... {
        move |...| { ... }
    }

    let x = ..;
    let y = ..;

    closure(x, y)
}
4 Likes

@sinkuu: This is pedantic -- and I'm willing to pay the runtime cost, but is there anyway to get the compiler to compile the closure(x,y) call away at compile time?

It will probably be inlined already, but you can hint further with #[inline] or #[inline(always)] on the function.

Does anybody know if it's feasible to write a clippy lint for this - does clippy have enough context to recognize which names are captured (vs. imports, for example)?