Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upeRFC: Experimentally add coroutines to Rust #2033
Conversation
This comment has been minimized.
This comment has been minimized.
nikomatsakis
added
the
T-lang
label
Jun 15, 2017
This comment has been minimized.
This comment has been minimized.
|
The only thing I can see that I don't immediately agree with is the "coroutine" terminology We have to be careful to avoid stabilizing a type like It'd be interesting to see how far people can get with emulating actual generators on top of plain |
This comment has been minimized.
This comment has been minimized.
eternaleye
commented
Jun 16, 2017
•
|
One nit I have, in the cleanliness/ergonomics domain - the example you give is an
Connected with this, what conversions should EDIT: Ah, I missed that you do specify the latter desugaring, though I think a clarification for EDIT 2 (Electric Boogaloo): One thing I do feel should be brought up is a specific section of this post by Joe Duffy about using asynchrony in Midori, and specifically using coroutines with async/await syntax sugar:
It may not be reasonable to insist on having a story for this right away, but I think there should at least be a story on having a story for it |
This comment has been minimized.
This comment has been minimized.
Sharing an |
This comment has been minimized.
This comment has been minimized.
bugaevc
commented on text/0000-experimental-coroutines.md in 2c4e068
Jun 16, 2017
|
Should be |
This comment has been minimized.
This comment has been minimized.
(Emphasis added.) It’s easy to overlook the latter part of the quoted sentence. I’d like the RFC to say that a path exists to eventually stabilize corountines (subject to future discussion and RFCs) for use cases other than async/await, for example for returning |
This comment has been minimized.
This comment has been minimized.
|
@arielb1 Ah, indeed, with the ability to put in a value and later take it out, |
est31
reviewed
Jun 16, 2017
| solving our problem! | ||
|
|
||
| Coroutines are, however, a little lower level than futures themselves. The | ||
| stackless coroutine feature can be used not only future futures but also other |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
So the RFC proposes to add stackless coroutines as experimental feature, but doesn't really describe what stackless coroutines would look like, and what the advantages of stackless coroutines are over stackfull ones. I'd like more on that, especially as I'm not certain how this RFC manages to avoid the issue of stackless coroutines that yielding is only possible from the top level coroutine. Is it the state machines? |
bestouff
and others
added some commits
Jun 16, 2017
This comment has been minimized.
This comment has been minimized.
|
I'm definitely in favour of this feature, although I'm still hoping that a generic "execution context" parameter is added to futures, similar to rust-lang-nursery/futures-rs#129, to replace the scoped thread-locals which are currently used. This would require the At the risk of encouraging further bike-shedding, would it be possible to add the details of the new types and traits to the RFC? |
This comment has been minimized.
This comment has been minimized.
ihrwein
commented
Jun 16, 2017
|
Do we really need the |
This comment has been minimized.
This comment has been minimized.
eternaleye
commented
Jun 16, 2017
•
|
@ihrwein The problem there is "What if you want to await on a future, but not early-return on error?" Catching On the other hand, I would be curious about making |
This comment has been minimized.
This comment has been minimized.
ihrwein
commented
Jun 16, 2017
|
@eternaleye That makes it clear, thanks. I believe if this pattern will be very common (await + ?), then ? could be extended to work with futures (although I see that they are somewhat orthogonal). |
This comment has been minimized.
This comment has been minimized.
camlorn
commented
Jun 16, 2017
|
I would like to see iterators made more of a focus here. I don't necessarily see making them a priority as more burdensome than making async/await work, since we essentially already have to. Our story for writing complex iterators from scratch is abysmal; I'd prefer us to not have to wait for another RFC/implementation/nightly cycle after this one. @est31 |
This comment has been minimized.
This comment has been minimized.
|
I just wanted to make a meta-comment about this RFC and the role that I see it playing. In discussions on internals and elsehwere, we've been going back and forth for some time about the best way to handle complex language extensions like coroutines, syntax extensions, embedded Rust support, and so forth. These are basically all cases where there seems to be a clear high-level need, but there is also a very large "design space" to explore. In such cases, it's not clear that writing up a detailed RFC is the best place to start. Often, a lot of the interesting questions only arise when you start putting the design into practice. Furthermore, even if we could write a big RFC, everybody is busy, and it's not clear that the various teams will have the time to really vet and approve something that complex. We've handled this in the past in a number of ways. Sometimes we can write up a kind of "conservative" RFC that describes a limited form of the feature (e.g., for To better handle these cases, I'm hoping we can kind of formalize an "experimental RFC" process. The idea is that we'll start with an "experimental RFC" like this one, that is primarily aimed at explaining the motivation and also a high-level sketch of what we plan to do. So, in this case, the motivation is that async-await is needed, and the high-level plan is that we hope to build it outside of the language, using two more fundamental features: procedural macros and some form of coroutine/generator syntax to do the state-machine transformation. The goal of this RFC is then to evaluate that high-level strategy and affirm that we think it's a promising path to explore. As such, I don't imagine that this RFC will require as much deliberation as other RFCs, since it's not making any kind of commitments or firm decisions. It's good for the RFC to also identify some of the questions that we intend to answer as we go, but we shouldn't expect it to have answers. Examples might be: what precisely should the async-await macros look like? How exactly will the coroutines be surfaced in Rust syntax, and what traits etc will they use? Those conversations can take place later, and as we come to conclusions, we should track the answers and be working on follow-up RFCs which will address them in particular. The key point then is that the experimental RFC is not enough to stabilize something. For that, we need a proper RFC that lays out the plan. This RFC can be informed by the experience and working implementation, so we should have a lot of data to use. Now, in a sort of meta-meta twist, I don't know how well this process will work. I view this experimental RFC as itself an experiment in process. The main thing I want to avoid is that we wind up with a lot of features that "work" but don't have much for a formal spec. We have enough of that grandfathered in already. ;) This is why I wanted to ensure we have a follow-up RFC, and I think we should be careful that when we land patches on "experimental code", we insist that it comes with good, well-organized test cases that document the behavior and the edge cases. In other words, just because something is experimental doesn't mean it has an excuse to be sloppy. (Ideally, we'd be trying to maintain some informal documentation in the nightly book, as well -- but I think this applies to all the nightly features.) The other concern of course is that we're going to be maintaining this code in master. It will interact with the rest of the system. It will cause regressions. In a way, this is a real strength: one of the things we want to be evaluating about a new feature is how it interacts with the rest of our system! But it's also a reason that we should all decide whether to take on that maintaince burden. |
This comment has been minimized.
This comment has been minimized.
I'd prefer if you could distinguish between "this might return in an error condition" and "this is an async break point". If the |
This comment has been minimized.
This comment has been minimized.
ivandardi
commented
Jun 16, 2017
|
@eternaleye Hm... How about this? Calling |
This comment has been minimized.
This comment has been minimized.
|
Now, in a non-meta comment, I'm very much in favor of this RFC and this general approach. It seems to me that "coroutines/generators" are the right fundamental primitive to start with; they can support so many different applications (iterators, as @camlorn points out, but also other "future-like" traits, as well as thinks like parsers and lexers). Having async-await work via syntax extension feels good to me since it puts all of these other kinds of applications on equal footing; they may want their own "wrapper" macros or types. I like that as a side-benefit of this work we will be improving syntax extensions, and in particular I imagine there will be a good focus on their error messages and so forth, since we'll want to make (One other observation: I think that our experience with A few responses to some comments I saw:
I do think these are good questions to raise, though I think that we don't have to settle them by any means to accept the RFC. In other words, figuring out the most ergonomic way to encode async-await feels like the kind of thing that we can do during the implementation period, and I wouldn't want this RFC to try and do it. But maybe it'd be good to start an internals thread or some other place to hammer out these details. (For example, another thing that occurs to me is that, since
This does seem like something that might be good to talk about, since choosing to build on stackless coroutines is a key building block here. I think one of the obvious advantages of stackless coroutines is that they don't really require any sort of "runtime", or at least they push that decision outward. If you use something where we allocate a stack ahead of time, then you have to decide who is allocating the stack and manage it -- you also run into some hard questions about what to do if the stack is not big enough, and so forth. I think @vadimcn's stackless coroutines RFC has a bit more here, although it doesn't talk as much about it.
I'm not sure if I think that should be in the RFC -- at minimum, I'd want to clearly label them as non-normative. But it's probably a good idea to try and write-up that description, perhaps posting it into the internals thread on the topic for more discussion. I also think that the we ought to document these things, at least in some form, in the unstable book in @Zoxc's branch.
I do think that's a great area to dig into, though I'd rather do it in a specific thread on the topic than here, since it's really a question of working out the fine details -- it's clear it will work in some form or another. For example, @vadimcn's RFC #1823 proposed blanket impls of
That's really slick, but this precise approach will likely run afoul of the existing coherence rules (although I just remembered that the (By the way, I think this is another good example of where the experimental process would help. That is, once we have the basic system implemented, we can make branches that experiment with various approaches around iterators and see what happens, in terms of its impact on existing impls etc.) |
This comment has been minimized.
This comment has been minimized.
This sort of thing also appeared in the |
This comment has been minimized.
This comment has been minimized.
|
First of all, I want to express how excited I am to see all the progress that has been made on this. It seems like it's being done in a methodical and careful way. I'm interested to see what we learn from having experience using this feature on nightly. One nit: I don't see any explicit mention in the RFC of why the |
This comment has been minimized.
This comment has been minimized.
contactomorph
commented
Jun 16, 2017
•
@alexcrichton I have bad feelings about the use of procedural macros for features like asynchronicity/generators/coroutines where keywords may be expected. Isn't this starting to make Rust really over-complicated for a supposed flexibility? I mean it's somehow providing the illusionary impression that the number of keywords is constant whereas - as I see it - it is in fact splitting the keyword space into two syntactical classes, one of them (procedural macros) being easier to extend. Aren't we creating another language inside the language? Maybe I haven't realised before this was the point of procedural macros to begin with. Am I the only one worried about this kind of consideration? |
This comment has been minimized.
This comment has been minimized.
|
Ok thanks for all the initial comments everyone! I've pushed an update with two pieces:
I believe the alternative is: impl<T: Coroutine> Future for T {
// ...
}(or something like that) I'd personally be very wary of such an impl in the I added an "open question" about this though in how the traits interact. This question/problem I'd expect is far more relevant to iterators, for example, as the translation between coroutines an iterators is in theory much simpler.
A good point! I've made sure to register this as an open question to make sure we loop back around to. For now though my hope is to keep this RFC as minimal as possible to impact on the compiler and make it as easy as possible in terms of maintenance burden to land in the compiler. Along those lines the choice of new keywords isn't taken for now. It's worth pointing out two imporant aspects, though. The historic The second point though is along the lines of what @nikomatsakis mentioned in his first response to @eternaleye. The Basically, I think the choice of syntax extensions early on provides us a maximal amount of flexibility moving forward. We can switch to keywords later, we can experiment with keywords right now. Lots of open possibilities! |
This comment has been minimized.
This comment has been minimized.
johansigfrids
commented
Jun 17, 2017
|
If the point of a experimental RFC is that it must be followed up by a proper RFC that lays out the details omitted by the eRFC would it make sense to have an Deferred Questions section, both to document what the the final RFC needs to cover and to be transparent about why the eRFC doesn't touch upon some topics? |
This comment has been minimized.
This comment has been minimized.
|
@johansigfrids The second half of the "Detailed design" section already is that list of questions. Are you saying there are some other questions that need to be added to it or that the list needs to be moved into a separate section to draw even more attention to it or something? |
This comment has been minimized.
This comment has been minimized.
rfcbot
commented
Jul 7, 2017
|
The final comment period is now complete. |
This comment has been minimized.
This comment has been minimized.
golddranks
commented
Jul 8, 2017
•
|
I wonder if we have a new record how fast the RFC process was for a feature of this caliber :D (The "experimental" part surely helped.) |
aturon
referenced this pull request
Jul 8, 2017
Open
Tracking issue for RFC 2033: Experimentally add coroutines to Rust #43122
aturon
merged commit b48970a
into
rust-lang:master
Jul 8, 2017
This comment has been minimized.
This comment has been minimized.
|
Huzzah! This experimental RFC has been merged! Tracking issue. For clarity: what this means is that we have approved exploration of this feature within the nightly compiler toolchain. After we have gained sufficient experience, we expect a full RFC to be filed and discussed, which will be the first step toward any eventual stabilization. (We may, of course, also decide not to pursue the feature at all). Thanks all for the far-ranging discussion! Those of you with specific thoughts about the way to structure |
jimmycuadra
referenced this pull request
Aug 16, 2017
Open
Things blocking or slowing progress of Ruma #189
scottmcm
referenced this pull request
Aug 17, 2017
Closed
Ok wrapping: Improved support for writing code from an error handling mindset #2107
bors
added a commit
to rust-lang/rust
that referenced
this pull request
Aug 27, 2017
bors
added a commit
to rust-lang/rust
that referenced
this pull request
Aug 28, 2017
bors
added a commit
to rust-lang/rust
that referenced
this pull request
Aug 28, 2017
bors
added a commit
to rust-lang/rust
that referenced
this pull request
Aug 28, 2017
bors
added a commit
to rust-lang/rust
that referenced
this pull request
Aug 28, 2017
willglynn
referenced this pull request
Aug 28, 2017
Open
Refactor MacOS and provide a coroutine-driven runloop #237
mbrubeck
referenced this pull request
Sep 28, 2017
Closed
A `yield` construct in the vein of C# #388
burdges
referenced this pull request
Feb 11, 2018
Open
Proposal: Auto-propagated function parameters #2327
This comment has been minimized.
This comment has been minimized.
reinit
commented
Mar 8, 2018
|
Sorry to bother you guys, just here to ask whether or not I'm currently trying to developing a website using Rust, but I found that some third-party external crates I needed does not support Async IO, which really hurts server performance a lot. Consider it's really really hard to ask all crate authors to uniformly use something like |
This comment has been minimized.
This comment has been minimized.
|
Just ask them to adopt tokio or something based on futures-rs. Those two are the standard. Optionally you can ask them to add an async mode so that people are not forced to pull in tokio or futures-rs. |
This comment has been minimized.
This comment has been minimized.
reinit
commented
Mar 9, 2018
•
|
Well, I must getting something wrong. I did a little research on the context and found that you guys are more leaned towards reduce the content that can be put into the standard library for some reason, maybe that's alright, but some features can really work better in the core. Some language already did that (to use standard library to introduce standards, not just put essential code), and they work wonderfully like a dream. Actually, if you look real close, Rust sort if did it too, But you guys still put them in there, presumably to provide something standard so everybody can be on the same table and be little happier? What would happen if those things does not existed in the Rust is a hard language already, please do something to make user's life easier. Bonus question: Why do people in the PHP world tend to build their project on top of a full stack framework rather than compose a custom framework by themselves, even they knew a full stack framework is often slower than the composed one? |
This comment has been minimized.
This comment has been minimized.
|
@reinit I'm afraid if you're looking for a production-ready async system with strong backwards compatibility guarantees, that's just not available yet. Moving it into the standard library won't help in that regard. |
This comment has been minimized.
This comment has been minimized.
reinit
commented
Mar 9, 2018
|
@Diggsey OK, then looks I need to wait a little while. Thank you. |
alexcrichton commentedJun 15, 2017
•
edited by aturon
This is an experimental RFC for adding a new feature to the language,
coroutines (also commonly referred to as generators). This RFC is intended to be
relatively lightweight and bikeshed free as it will be followed by a separate
RFC in the future for stabilization of this language feature. The intention here
is to make sure everyone's on board with the general idea of
coroutines/generators being added to the Rust compiler and available for use on
the nightly channel.
Rendered
What's a experimental RFC?