-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Allow closures to mutate their upvars #4093
Comments
What about using
With type-based move (on incoming) it shouldn't require a capture clause to move If the allocation is a problem one could have a struct with a mutable field. Of course, mutable fields are probably going away, making that not work. If moves based on type also applied to mutable types and you could mutate captures, then your original example could work as written. |
@pcwalton says mutable types also move by default, so seemingly the only missing piece is to allow mutable closure environments. |
It turns out that we really want this as part of the plan to remove |
I should add that this should be discussed in a group meeting, I think. |
We never had consensus here, so I'm going to courageously close this. Of course, someone else could always courageously reopen it. |
I don't know that we ever discussed this in detail? I think it's an important feature, though, particularly if we want to avoid the need for a type like |
@nikomatsakis No, we didn't discuss it -- I reasoned that if there had been sufficient interest, the discussion would have happened by now :-) Perhaps we can put it on the agenda for the next meeting. |
Updated title. I consider this a sub-piece of #2202 |
Nominated the meta bug. |
Triage: don't really understand this. cc #9351 since it can be used as a work around for this issue. |
Closing, |
Rust does not permit the following code:
It is disallowed for two reasons:
These restrictions appear to primarily have historical motivations: originally, local variables were all mutable and were captured by copying their values at the time the closure was created.
However, it is often convenient to create a "stateful" heap closure, which maintains some hidden local state that may change between calls to it. The most natural way to do this is to allow heap closures to capture mutable variables by reference.
If we allowed this, then
generate_nats_from(0)
would return a functionf
such that the first call tof
returned 1, the second 2, the third 3, etc. This is very similar to a python-style generator, albeit written explicitly instead of withyield
.To achieve this currently in rust, we must explicitly allocate a mutable managed pointer, like so:
Notice that I had to drop the
pure
annotation on the returned function, because it mutates an @-pointer. However, the function is notionally pure: it mutates nothing visible to its caller, only its own internal state.It also makes the code uglier, and in principle less efficient, to do it this way. I say "in principle less efficient" because the code given allocates a separate GC'd box for
x
, when it could instead become part of the environment of the closure we return. Actually implementing this optimization, however, might be difficult.Mostly I want this feature because it makes writing stateful closures nicer, and it makes writing pure stateful closures possible.
For examples of code that could benefit from this, see https://github.com/rntz/rust-sandbox/blob/master/stream.rs , in particular https://github.com/rntz/rust-sandbox/blob/905de30e5a7af8422ea3604b90f6443745bf6233/stream.rs#L30 and https://github.com/rntz/rust-sandbox/blob/905de30e5a7af8422ea3604b90f6443745bf6233/stream.rs#L101 .
Note in particular that the only thing keeping most of the functions in that module, and the definition of the
Stream
type itself, from being pure is this issue. As far as I can tell, lazy streams of this sort are doomed to second-class citizenship in the Rust purity system as long as this is not permitted.The text was updated successfully, but these errors were encountered: