-
Notifications
You must be signed in to change notification settings - Fork 13.7k
Description
I am exploring how the Copy
trait is implicitly added to closures as in this RFC. As a simple example, let's say I create a function foo
which takes a Copy
closure.
fn foo(f: impl Fn(i32) + Copy) {
f(10);
}
Although in this case f
does not need to be Copy
, this is just to simplify the example, let's pretend that it really does. Now I create a function bar
which returns the same type of closure that foo
accepts.
fn bar() -> impl Fn(i32) {
|x: i32| {
println!("{}", x);
}
}
From my reading of the RFC, the returned closure should implicitly implement Copy
. However, if I try to call foo
with the result from bar
, the compiler gives me an error because I do not explicitly implement Copy
on the closure returned by bar
.
foo(bar());
^^^^^ the trait `std::marker::Copy` is not implemented for `impl std::ops::Fn<(i32,)>`
Whilst I could change the signature of bar
to return impl Fn(i32) + Copy
let's assume that I do not have control over this function as it is defined in another crate. Interestingly, if I wrap the whole thing in another (and pointless!) closure, it works 👀
foo(|x: i32| bar()(x));
I have seen this exact pattern come up when using combinator libraries (nom for instance), and the second working solution is pretty frustrating as the outer closure has no purpose.
-
Is this the intended behaviour of the Rust compiler? Surely this is a bug that it can only infer
Copy
on local closures and not those returned by functions? -
Is there something simple I'm missing; maybe I can write this in another way to avoid this issue? For this, please assume that I cannot edit
foo
orbar
as this is based on real examples where combinators I use are defined by other crates.
Thank you! 😄