-
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
Add support for for await
loops
#118847
Add support for for await
loops
#118847
Conversation
Yeah, I think this could use a lang-ok. |
Oh, I also need to add a test to make sure we don't parse |
I also think this should be a separate feature gate, |
This comment has been minimized.
This comment has been minimized.
The proposed desugaring doesn't seem great. It'll have to poll a future and then match an option on each loop iteration, which means 2 conditions per iteration which is just terrible for optimizations. It's already hard to make regular for loop desugaring efficient and in some cases internal iteration still outperforms it. This would be much worse. I think a pattern closer to nonblocking IO would be better where one keeps reading until EAGAIN and only then polls (awaits). That way things could be split into an inner next() + outer await loop. Alternatively an async equivalent to |
Perhaps the signature of |
This comment has been minimized.
This comment has been minimized.
Okay, I've reworked this PR significantly to get rid of |
This comment has been minimized.
This comment has been minimized.
Hi, While I appreciate the efforts to introduce for await loops in Rust, I have some reservations about the proposed syntax and semantics. In the current design, await is consistently used as a postfix operator (.await). Introducing for await breaks this consistency, potentially leading to confusion. The semantic clarity of await as a postfix operator has been a strong point in Rust's async design, and deviating from this pattern might weaken the language's overall coherence. Personally, I would advocate for a syntax more in line with the existing async constructs. For example, I believe this change warrants a more extensive discussion within the community. The introduction of a new syntax, especially one that deviates from established patterns, is a significant decision. It's crucial to consider the implications on the language's learning curve, consistency, and future extensibility. While I support the initiative to enhance async iteration in Rust, I would urge reconsideration of the syntax to align better with existing conventions. A broader discussion might yield a more agreeable and consistent solution. |
Note that in edition 2015 |
It does not introduce a new |
Keep in mind that this is just a nightly experiment at this point. No sticky decisions have been made on these details and they are still the subject of much reflection and discussion among the people working on this. The purpose of the nightly experiment is to collect the kind of experience that can only come from implementing and trying the feature in nightly so that we can better write an RFC. While feedback and participation is of course welcome here, the RFC process will be the main venue for the extensive discussion with the community that you mention. |
Add support for `for await` loops This adds support for `for await` loops. This includes parsing, desugaring in AST->HIR lowering, and adding some support functions to the library. Given a loop like: ```rust for await i in iter { ... } ``` this is desugared to something like: ```rust let mut iter = iter.into_async_iter(); while let Some(i) = loop { match core::pin::Pin::new(&mut iter).poll_next(cx) { Poll::Ready(i) => break i, Poll::Pending => yield, } } { ... } ``` This PR also adds a basic `IntoAsyncIterator` trait. This is partly for symmetry with the way `Iterator` and `IntoIterator` work. The other reason is that for async iterators it's helpful to have a place apart from the data structure being iterated over to store state. `IntoAsyncIterator` gives us a good place to do this. I've gated this feature behind `async_for_loop` and opened rust-lang#118898 as the feature tracking issue. r? `@compiler-errors`
The job Click to see the possible cause of the failure (guessed by this bot)
|
💔 Test failed - checks-actions |
No idea what's up with the test failure.. @bors retry |
Add support for `for await` loops This adds support for `for await` loops. This includes parsing, desugaring in AST->HIR lowering, and adding some support functions to the library. Given a loop like: ```rust for await i in iter { ... } ``` this is desugared to something like: ```rust let mut iter = iter.into_async_iter(); while let Some(i) = loop { match core::pin::Pin::new(&mut iter).poll_next(cx) { Poll::Ready(i) => break i, Poll::Pending => yield, } } { ... } ``` This PR also adds a basic `IntoAsyncIterator` trait. This is partly for symmetry with the way `Iterator` and `IntoIterator` work. The other reason is that for async iterators it's helpful to have a place apart from the data structure being iterated over to store state. `IntoAsyncIterator` gives us a good place to do this. I've gated this feature behind `async_for_loop` and opened rust-lang#118898 as the feature tracking issue. r? `@compiler-errors`
💥 Test timed out |
@bors retry |
☀️ Test successful - checks-actions |
Finished benchmarking commit (208dd20): comparison URL. Overall result: ❌ regressions - no action needed@rustbot label: -perf-regression Instruction countThis is a highly reliable metric that was used to determine the overall result at the top of this comment.
Max RSS (memory usage)ResultsThis is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
CyclesResultsThis is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.
Binary sizeThis benchmark run did not return any relevant results for this metric. Bootstrap: 674.428s -> 674.366s (-0.01%) |
since merge happened, I'll assume the I-async nomination can be now removed @rustbot label -I-async-nominated |
Add support for `for await` loops This adds support for `for await` loops. This includes parsing, desugaring in AST->HIR lowering, and adding some support functions to the library. Given a loop like: ```rust for await i in iter { ... } ``` this is desugared to something like: ```rust let mut iter = iter.into_async_iter(); while let Some(i) = loop { match core::pin::Pin::new(&mut iter).poll_next(cx) { Poll::Ready(i) => break i, Poll::Pending => yield, } } { ... } ``` This PR also adds a basic `IntoAsyncIterator` trait. This is partly for symmetry with the way `Iterator` and `IntoIterator` work. The other reason is that for async iterators it's helpful to have a place apart from the data structure being iterated over to store state. `IntoAsyncIterator` gives us a good place to do this. I've gated this feature behind `async_for_loop` and opened rust-lang#118898 as the feature tracking issue. r? `@compiler-errors`
Add support for `for await` loops This adds support for `for await` loops. This includes parsing, desugaring in AST->HIR lowering, and adding some support functions to the library. Given a loop like: ```rust for await i in iter { ... } ``` this is desugared to something like: ```rust let mut iter = iter.into_async_iter(); while let Some(i) = loop { match core::pin::Pin::new(&mut iter).poll_next(cx) { Poll::Ready(i) => break i, Poll::Pending => yield, } } { ... } ``` This PR also adds a basic `IntoAsyncIterator` trait. This is partly for symmetry with the way `Iterator` and `IntoIterator` work. The other reason is that for async iterators it's helpful to have a place apart from the data structure being iterated over to store state. `IntoAsyncIterator` gives us a good place to do this. I've gated this feature behind `async_for_loop` and opened rust-lang#118898 as the feature tracking issue. r? `@compiler-errors`
This adds support for
for await
loops. This includes parsing, desugaring in AST->HIR lowering, and adding some support functions to the library.Given a loop like:
this is desugared to something like:
This PR also adds a basic
IntoAsyncIterator
trait. This is partly for symmetry with the wayIterator
andIntoIterator
work. The other reason is that for async iterators it's helpful to have a place apart from the data structure being iterated over to store state.IntoAsyncIterator
gives us a good place to do this.I've gated this feature behind
async_for_loop
and opened #118898 as the feature tracking issue.r? @compiler-errors