Skip to content

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

Closed
@reem

Description

@reem
Contributor

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.

Activity

japaric

japaric commented on Dec 15, 2014

@japaric
Member

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

ghost commented on Jan 11, 2015

@ghost

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

steveklabnik commented on Jan 4, 2016

@steveklabnik
Member

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

bluss

bluss commented on Jan 4, 2016

@bluss
Member

They were deliberately made non-copy in issue #19817

huonw

huonw commented on Jan 5, 2016

@huonw
Member

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

steveklabnik commented on Jan 5, 2016

@steveklabnik
Member

Thanks @bluss !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-closuresArea: Closures (`|…| { … }`)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @steveklabnik@huonw@bluss@reem@japaric

        Issue actions

          Unboxed closures with no or only-Copy captures should be Copy · Issue #19128 · rust-lang/rust