Skip to content

Unboxed closures with no or only-Copy captures should be Copy #19128

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
reem opened this issue Nov 20, 2014 · 6 comments
Closed

Unboxed closures with no or only-Copy captures should be Copy #19128

reem opened this issue Nov 20, 2014 · 6 comments
Labels
A-closures Area: Closures (`|…| { … }`)

Comments

@reem
Copy link
Contributor

reem commented Nov 20, 2014

Right now no unboxed closures are Copy, but there's no reason that 0-size closures or those with only copy captures couldn't be Copy.

@huonw huonw added the A-closures Area: Closures (`|…| { … }`) label Nov 25, 2014
@japaric
Copy link
Member

japaric commented Dec 15, 2014

This is solved, unboxed closures are currently copyable:

fn is_copy<T: Copy>(_: T) {}

fn main() {
    let i = 5i;
    is_copy(move |:| i);
    is_copy(|&:| {});
    is_copy(|&mut :| {});
    is_copy(|:| i);
    is_copy(|:| {});
}

But according to #19817 and #19889, the plan is that they shouldn't be implicitly copyable (which I don't quite agree with).

@ghost
Copy link

ghost commented Jan 11, 2015

So apparently the changes to make the trait Copy opt-in for closures have been implemented, which means that the code above doesn't work any more.
But can somebody explain how I can actually opt-in for the Copy trait when declaring a closure?

@steveklabnik
Copy link
Member

Triage: closures aren't copyable again, but I am not sure if they're intended to be or not. @rust-lang/lang?

@bluss
Copy link
Member

bluss commented Jan 4, 2016

They were deliberately made non-copy in issue #19817

@huonw
Copy link
Member

huonw commented Jan 5, 2016

But can somebody explain how I can actually opt-in for the Copy trait when declaring a closure?

There's a few possible ways to have duplicatable closures (all aren't great, unfortunately):

  • pass a & reference instead of the closure itself (&F implements Fn when F itself does), which implements Copy
  • use Rc<F> (possibly a trait object), similar to the above, but this can be stored/returned (only implements Clone
  • write fn foo<F, G>(f: F) where F: Fn() -> G, G: Fn(...) -> ... instead of fn foo<F>(f: F) where F: Fn(...) -> ..., where the F closure creates new instances of the actual closure of interest (G), effectively behaving as the clone function. I suspect this often works as just foo(|| |actual| closure), i.e. just add || at the start of the closure.

These have various downsides e.g. the first two only work for Fn (not FnMut or FnOnce), the first cannot be returned from functions/stored inside return values, the second doesn't integrate with generics quite as well as others, and the third is rather ugly.

@steveklabnik
Copy link
Member

Thanks @bluss !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-closures Area: Closures (`|…| { … }`)
Projects
None yet
Development

No branches or pull requests

5 participants