Auto merge of #118847 - eholk:for-await, 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 #118898 as the feature tracking issue. r? `@compiler-errors`
This commit is contained in:
commit
b29b02ca5b
@ -448,7 +448,7 @@ fn is_block_closure_forced(context: &RewriteContext<'_>, expr: &ast::Expr) -> bo
|
||||
|
||||
fn is_block_closure_forced_inner(expr: &ast::Expr, version: Version) -> bool {
|
||||
match expr.kind {
|
||||
ast::ExprKind::If(..) | ast::ExprKind::While(..) | ast::ExprKind::ForLoop(..) => true,
|
||||
ast::ExprKind::If(..) | ast::ExprKind::While(..) | ast::ExprKind::ForLoop { .. } => true,
|
||||
ast::ExprKind::Loop(..) if version == Version::Two => true,
|
||||
ast::ExprKind::AddrOf(_, _, ref expr)
|
||||
| ast::ExprKind::Try(ref expr)
|
||||
@ -473,7 +473,7 @@ fn expr_requires_semi_to_be_stmt(e: &ast::Expr) -> bool {
|
||||
| ast::ExprKind::Block(..)
|
||||
| ast::ExprKind::While(..)
|
||||
| ast::ExprKind::Loop(..)
|
||||
| ast::ExprKind::ForLoop(..)
|
||||
| ast::ExprKind::ForLoop { .. }
|
||||
| ast::ExprKind::TryBlock(..) => false,
|
||||
_ => true,
|
||||
}
|
||||
|
24
src/expr.rs
24
src/expr.rs
@ -3,7 +3,7 @@
|
||||
|
||||
use itertools::Itertools;
|
||||
use rustc_ast::token::{Delimiter, Lit, LitKind};
|
||||
use rustc_ast::{ast, ptr, token};
|
||||
use rustc_ast::{ast, ptr, token, ForLoopKind};
|
||||
use rustc_span::{BytePos, Span};
|
||||
|
||||
use crate::chains::rewrite_chain;
|
||||
@ -134,7 +134,7 @@ pub(crate) fn format_expr(
|
||||
}
|
||||
ast::ExprKind::Let(ref pat, ref expr, _span, _) => rewrite_let(context, shape, pat, expr),
|
||||
ast::ExprKind::If(..)
|
||||
| ast::ExprKind::ForLoop(..)
|
||||
| ast::ExprKind::ForLoop { .. }
|
||||
| ast::ExprKind::Loop(..)
|
||||
| ast::ExprKind::While(..) => to_control_flow(expr, expr_type)
|
||||
.and_then(|control_flow| control_flow.rewrite(context, shape)),
|
||||
@ -682,9 +682,15 @@ fn to_control_flow(expr: &ast::Expr, expr_type: ExprType) -> Option<ControlFlow<
|
||||
expr.span,
|
||||
))
|
||||
}
|
||||
ast::ExprKind::ForLoop(ref pat, ref cond, ref block, label) => {
|
||||
Some(ControlFlow::new_for(pat, cond, block, label, expr.span))
|
||||
}
|
||||
ast::ExprKind::ForLoop {
|
||||
ref pat,
|
||||
ref iter,
|
||||
ref body,
|
||||
label,
|
||||
kind,
|
||||
} => Some(ControlFlow::new_for(
|
||||
pat, iter, body, label, expr.span, kind,
|
||||
)),
|
||||
ast::ExprKind::Loop(ref block, label, _) => {
|
||||
Some(ControlFlow::new_loop(block, label, expr.span))
|
||||
}
|
||||
@ -771,6 +777,7 @@ fn new_for(
|
||||
block: &'a ast::Block,
|
||||
label: Option<ast::Label>,
|
||||
span: Span,
|
||||
kind: ForLoopKind,
|
||||
) -> ControlFlow<'a> {
|
||||
ControlFlow {
|
||||
cond: Some(cond),
|
||||
@ -778,7 +785,10 @@ fn new_for(
|
||||
else_block: None,
|
||||
label,
|
||||
pat: Some(pat),
|
||||
keyword: "for",
|
||||
keyword: match kind {
|
||||
ForLoopKind::For => "for",
|
||||
ForLoopKind::ForAwait => "for await",
|
||||
},
|
||||
matcher: "",
|
||||
connector: " in",
|
||||
allow_single_line: false,
|
||||
@ -1364,7 +1374,7 @@ pub(crate) fn can_be_overflowed_expr(
|
||||
|| context.config.overflow_delimited_expr()
|
||||
}
|
||||
ast::ExprKind::If(..)
|
||||
| ast::ExprKind::ForLoop(..)
|
||||
| ast::ExprKind::ForLoop { .. }
|
||||
| ast::ExprKind::Loop(..)
|
||||
| ast::ExprKind::While(..) => {
|
||||
context.config.combine_control_expr() && context.use_block_indent() && args_len == 1
|
||||
|
@ -591,7 +591,7 @@ fn can_flatten_block_around_this(body: &ast::Expr) -> bool {
|
||||
ast::ExprKind::If(..) => false,
|
||||
// We do not allow collapsing a block around expression with condition
|
||||
// to avoid it being cluttered with match arm.
|
||||
ast::ExprKind::ForLoop(..) | ast::ExprKind::While(..) => false,
|
||||
ast::ExprKind::ForLoop { .. } | ast::ExprKind::While(..) => false,
|
||||
ast::ExprKind::Loop(..)
|
||||
| ast::ExprKind::Match(..)
|
||||
| ast::ExprKind::Block(..)
|
||||
|
@ -409,7 +409,7 @@ fn rewrite_last_item_with_overflow(
|
||||
// When overflowing the expressions which consists of a control flow
|
||||
// expression, avoid condition to use multi line.
|
||||
ast::ExprKind::If(..)
|
||||
| ast::ExprKind::ForLoop(..)
|
||||
| ast::ExprKind::ForLoop { .. }
|
||||
| ast::ExprKind::Loop(..)
|
||||
| ast::ExprKind::While(..)
|
||||
| ast::ExprKind::Match(..) => {
|
||||
|
@ -295,7 +295,7 @@ pub(crate) fn semicolon_for_stmt(
|
||||
) -> bool {
|
||||
match stmt.kind {
|
||||
ast::StmtKind::Semi(ref expr) => match expr.kind {
|
||||
ast::ExprKind::While(..) | ast::ExprKind::Loop(..) | ast::ExprKind::ForLoop(..) => {
|
||||
ast::ExprKind::While(..) | ast::ExprKind::Loop(..) | ast::ExprKind::ForLoop { .. } => {
|
||||
false
|
||||
}
|
||||
ast::ExprKind::Break(..) | ast::ExprKind::Continue(..) | ast::ExprKind::Ret(..) => {
|
||||
@ -476,7 +476,7 @@ pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr
|
||||
| ast::ExprKind::ConstBlock(..)
|
||||
| ast::ExprKind::Gen(..)
|
||||
| ast::ExprKind::Loop(..)
|
||||
| ast::ExprKind::ForLoop(..)
|
||||
| ast::ExprKind::ForLoop { .. }
|
||||
| ast::ExprKind::TryBlock(..)
|
||||
| ast::ExprKind::Match(..) => repr.contains('\n'),
|
||||
ast::ExprKind::Paren(ref expr)
|
||||
|
Loading…
Reference in New Issue
Block a user