-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Distinguish closures from callables #3300
Conversation
text/0000-struct-closure.md
Outdated
# Guide-level explanation | ||
[guide-level-explanation]: #guide-level-explanation | ||
|
||
Closures in Rust are represented by the struct `core::ops::Closure`, while |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not see such a struct. Can you please link to it? Or are you proposing that this become what happens?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The RFC template says to write here "as if [the proposal] was already included in the language". This is that.
Tho we certainly may have taken that too literally.
currently closures acts like anonymous structs that captures its environment. But very importantly there's no identical closure. How does the proposed core::ops:: Closures reflect that? |
That's what the internal callable ( // this is not a closure, because a closure can't have both impls.
struct CustomCallable;
impl Fn(char) -> bool for CustomCallable {
...
}
impl Fn(&char) -> bool for CustomCallable {
...
} In other words, closures explicitly cannot do this (and, if we get this RFC, then we can guarantee this will never become accepted): fn foo<F: Fn(char) -> bool + Fn(&char) -> bool>(f: F) {
todo!();
}
fn main() {
foo(|x| true);
} (Interestingly, rustc attempts to infer the closure signature to whatever comes first here. In this case, that's |
I believe the solution is to disallow implementing |
Introducing a wrapper struct is free. Turning |
It took some significant reading to collapse my mental model of a problem statement into the following summary:
Does the above seem correct, @SoniEx2? Assuming that it is, I see several issues1 with this proposal that have a common thread: it proposes a language-level solution to an under-specified problem.
Footnotes
|
Yes, that is the entire motivation/issue, reason it needs to be baked into the language, and desired end state. Spite is still a pretty strong motivator and absolutely belongs in the motivation section of this proposal. |
In case it wasn't clear, I have made no suggestion that you remove mention of spite, or that it doesn't belong. On the contrary, emotional impact can be important context, and I don't see anything wrong with the way you've expressed it. Let's just make sure that people who haven't had first-hand experience feeling spite for this API can relate too. 😉 |
The "Summary" section is not a summary. It should be AT LEAST one sentence summarizing the feature, and not just 3 words that tell you nothing unless you are already familiar with it. Likewise, the "Motivation" section needs to be expanded. It should explain what is the current situation and why it is bad. |
The alternate way I wanted to solve this was to allow auto-(de)ref to apply just as it does for explicit function and method calls: fn x(_: &str) {}
fn y(_: impl Fn(&String)) {}
fn main() {
y(|v| x(v)); // Works
y(x); // Does not work
} |
There are certainly a lot of alternatives to pick from, the only question is which one is most appropriate. We do wonder if For another, definitely more verbose, but zero-cost alternative: could we |
(any feedback on the updated version/etc? we kinda put some of the motivation in the summary and we're not sure how to split it back out but it's probably okay??? at least for now?) also hmm, future possibility...? the ability to convert a ZST closure into an |
I'm concerned about the "unauthorized experimental collaborative process" you mentioned... What does that even mean? I clicked the link and then the page shows me something called MMO RFC??? |
It means we welcome anyone to edit the proposed RFC almost like it's a wiki. Because the "GAnarchy" thing we linked? It's basically a "wiki of git repos". |
It literally doesn’t matter because there is no “authorized” way of creating an RFC. |
Sure, but it's not like "making a wiki for it" is the expected way of creating RFCs. 😅 We hope that's fine tho. |
Hmm, why did this get such an overwhelmingly negative response? Btw, future work could've included giving |
apparently rust-lang/rust#84366 means we can't have this. :( |
it's unfortunate that fundamental traits are such a huge hack that even doing it properly (like with this RFC) wouldn't allow their removal... |
Rendered
This proposal introduces a struct
core::ops::Closure
, which represents a "concrete" form of closures and allows trait impls to distinguish closures from other kinds of callables. This distinction brings restrictions Rust applies to closures, to the type system, like how closures strictly support only a singleFn*
signature; having this restriction visible at the type level allows the same trait to be implemented for multiple closure signatures.In particular, this proposal aims to solve a historical
std
API design problem where somechar
methods, particularly thechar::is_ascii*
family of functions, cannot be used asstd::str::pattern::Pattern
s, due to requiring&self
as a receiver, whilePattern
is only implemented forFnMut(char) -> bool
, i.e.:We're also attempting to write this RFC using an unauthorized experimental collaborative process. We're hoping this helps things along, tho we still have no idea if it works. We also couldn't figure out how to
git merge --allow-unrelated-histories
so if we end up with other contributors we'll just have to manually make the merge commit object we guess.