-
-
Notifications
You must be signed in to change notification settings - Fork 14.1k
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
Copyon 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
fooorbaras this is based on real examples where combinators I use are defined by other crates.
Thank you! 😄