-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
Add one-shot closures #2549
Comments
a long time back I blogged about some thoughts in this direction. I still think this makes sense; it seems like the use cases are a bit clearer now than they were then. Interestingly, |
Marking as RFC. |
We had some discussion about this a while ago and it seems like we might be able to do this with just the kinds on the closure. It will require some type system tweaks though. |
Can it be at most once, or does it have to be exactly once? I favour this - the call-exactly-once pattern is quite common. For example, is this ok?
|
+1. GHC has a notion of "one-shot lambdas", too, fwiw. |
I think there's probably cases where we would want both "at least once" and "at most once." At least once:
At least once guarantees that With at most once, we gain the ability to move out of a closure during the function call. Also, with both at most once and at least once we can have exactly once too. |
I think "at least once" is going to be somewhat tricky. We have to think about what it means, e.g., to fail when you have not executed such a closure. Our lack of recoverable exceptions should help here though. I guess it means that the closure cannot be dropped except in the case of failure? Still, it makes me nervous. At most once seems much closer to what we have. |
Nominated so that Cell becomes less necessary. |
This is partly implemented. I believe the type system support is generally ok but there is no integration with liveness and trans. The most straight-forward way to update liveness is to modify it into a forward-propagating system (most of the infrastructure for which is being added for borrowck). Forward propagation means that it will be hard to emit existing warnings regarding dead assignments, unless we keep the existing liveness code around just for that purpose. In a meeting it was discussed moving to a control-flow graph for this purpose: I think this is a good long-term plan but I found the design constraints somewhat non-obvious so decided to defer until a first version of #5074 is done. (In particular, if we do a plain-jane CFG, we could probably use it for data-flow but not much else, whereas a somewhat more advanced CFG could simplify liveness, borrow checker, trans and numerous other passes by making explicit some of the implicit transformations that take place today such adjustments, for loop closures, etc) |
While this looks like "just an addition", it'll probably change all library APIs, so it's a backwards compatibility hazard. |
I don't think it's a backwards compatibility hazard... a library with The only place
Then you couldn't use it with:
But, if you ship rust-1.0 without |
By the way, what do y'all think of a compiler warning to warn when an argument closure is not declared The possible problem would be if you had a function that currently only called a function once but didn't want to provide that guarantee to the caller. So there would have to be a way to squelch the warning without taking its suggestion. e.g.:
would produce something like |
I went through the libraries and looked for use cases where one-shot closures would let us avoid using Cells specifically in the case of stack closures, assuming heap closures get replaced by traits, in an attempt to motivate needing one-shot functions anyway. Results are as follows:
|
When stack closures become noncopyable, |
It's currently really hard to use noncopyable data with things like
vec::each
oruint::range
, since the type system doesn't know how many times these functions will invoke their closures. It'd be nice to have some way for the compiler to know that a closure will be called at most once, so it can be safe to move out of upvars in these closures.The text was updated successfully, but these errors were encountered: