-
Notifications
You must be signed in to change notification settings - Fork 12.3k
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
Copy not implemented on returned closures #68307
Comments
If you would like to try this out for yourself, I have created this example on the playground |
You have to write fn foo(f: impl Fn(i32) + Copy) {
f(10);
}
fn bar() -> impl Fn(i32) + Copy {
|x: i32| {
println!("{}", x);
}
}
fn main() {
foo(bar());
} |
@rodrimati1992 Thanks for your reply! I am aware of this however please see my question above for why I can't do this... I have encountered this exact problem! My issue is that the compiler seems able to infer implicit |
That's how |
Right, but the Rust compiler can figure out the |
Yes, this is intended behavior. Only |
@Centril Okay, would there be a possible change to the compiler/language that could fix this? Or alternatively, is there another way that currently exists to achieve what I'm trying to do in a nicer way? |
Possible? Yes. Desirable? Unlikely, as it would require special casing I'm not aware of other ways at this time. |
@Centril Thanks, that's really helpful! I have a few questions about this...
|
That's the wrong RFC (you want the
I don't know enough about your use case to say I'm afraid. |
@Centril Okay, thanks I understand. For me, the solution of Therefore, although there may not currently be an easy way to resolve this, since the underlying issue has not been solved, would it be possible to re-open it as a feature request / request for suggestions as others may have further ideas on how this can be improved? Alternatively, is this better suited to an RFC and/or is there additional information I can provide to help clarify where the problem occurs? |
I suppose it can't hurt, though I don't think it will be actionable in the foreseeable future. |
I was surprised adding another layer of closure "helps", but it turns out to be a red herring. The reason let closure: !Copy = bar()
(|x: i32| closure(x)) : Copy is because let closure: !Copy = bar()
(move |x: i32| closure(x)) : !Copy you get the expected error of closure not implementing Inferring Consider a crate that consciously avoids adding the |
@nagisa I'm not sure this is true, take a look at this playground example.
As
So the reason (again, I think) this works is because Rust is able to automatically infer the type of the outer closure as it is declared inline and make it implicitly |
My bad, I cut some corners in my explanation. Please see the updated code samples in my previous comments and this playground. This should be sufficient to mis-prove your current intuition. EDIT: in the original examples we were indeed capturing |
@nagisa Hmmm... yeah you're right that's really interesting! Any ideas of how to solve this or perhaps nicer ways to tell the compiler that the closure is |
How about passing in a reference to the closure? Note, however that this only works for |
@nagisa Nevermind the following paragraphs,I don't think I've read you correctly. Passing a type that implements |
@nagisa Thanks, that's really nice actually! Am I right that this works because the |
Yes.
Yes.
The previous two points are perfectly sound and logical in isolation, so I’m not sure why it would be cheating to combine them to achieve something else. In fact the "wrapping in a closure" trick abuses exactly the same rules, just not as obviously. Anyway, closing this as there is nothing actionable to do here. For further support, consider posting your questions on users.rlo, stackoverflow, reddit, or discussing it on one of the chat platforms: discord or zulip. |
Fair enough, I think this is now a great solution and I hope the discussion will be helpful to anyone else with the same issue. Thanks for all the help 😍 |
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 functionfoo
which takes aCopy
closure.Although in this case
f
does not need to beCopy
, this is just to simplify the example, let's pretend that it really does. Now I create a functionbar
which returns the same type of closure thatfoo
accepts.From my reading of the RFC, the returned closure should implicitly implement
Copy
. However, if I try to callfoo
with the result frombar
, the compiler gives me an error because I do not explicitly implementCopy
on the closure returned bybar
.Whilst I could change the signature of
bar
to returnimpl 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 👀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! 😄
The text was updated successfully, but these errors were encountered: