Skip to content

Commit caa63dc

Browse files
committed
Plumb awaitness of for loops
1 parent 4f47328 commit caa63dc

File tree

22 files changed

+95
-52
lines changed

22 files changed

+95
-52
lines changed

compiler/rustc_ast/src/ast.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1261,7 +1261,7 @@ impl Expr {
12611261
ExprKind::Let(..) => ExprPrecedence::Let,
12621262
ExprKind::If(..) => ExprPrecedence::If,
12631263
ExprKind::While(..) => ExprPrecedence::While,
1264-
ExprKind::ForLoop(..) => ExprPrecedence::ForLoop,
1264+
ExprKind::ForLoop { .. } => ExprPrecedence::ForLoop,
12651265
ExprKind::Loop(..) => ExprPrecedence::Loop,
12661266
ExprKind::Match(..) => ExprPrecedence::Match,
12671267
ExprKind::Closure(..) => ExprPrecedence::Closure,
@@ -1423,10 +1423,10 @@ pub enum ExprKind {
14231423
While(P<Expr>, P<Block>, Option<Label>),
14241424
/// A `for` loop, with an optional label.
14251425
///
1426-
/// `'label: for pat in expr { block }`
1426+
/// `'label: for await? pat in iter { block }`
14271427
///
14281428
/// This is desugared to a combination of `loop` and `match` expressions.
1429-
ForLoop(P<Pat>, P<Expr>, P<Block>, Option<Label>),
1429+
ForLoop { pat: P<Pat>, iter: P<Expr>, body: P<Block>, label: Option<Label>, is_await: bool },
14301430
/// Conditionless loop (can be exited with `break`, `continue`, or `return`).
14311431
///
14321432
/// `'label: loop { block }`

compiler/rustc_ast/src/mut_visit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1388,7 +1388,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
13881388
vis.visit_block(body);
13891389
visit_opt(label, |label| vis.visit_label(label));
13901390
}
1391-
ExprKind::ForLoop(pat, iter, body, label) => {
1391+
ExprKind::ForLoop{pat, iter, body, label, is_await: _} => {
13921392
vis.visit_pat(pat);
13931393
vis.visit_expr(iter);
13941394
vis.visit_block(body);

compiler/rustc_ast/src/util/classify.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub fn expr_requires_semi_to_be_stmt(e: &ast::Expr) -> bool {
1919
| ast::ExprKind::Block(..)
2020
| ast::ExprKind::While(..)
2121
| ast::ExprKind::Loop(..)
22-
| ast::ExprKind::ForLoop(..)
22+
| ast::ExprKind::ForLoop { .. }
2323
| ast::ExprKind::TryBlock(..)
2424
| ast::ExprKind::ConstBlock(..)
2525
)
@@ -46,8 +46,15 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option<&ast::Expr> {
4646
Closure(closure) => {
4747
expr = &closure.body;
4848
}
49-
Gen(..) | Block(..) | ForLoop(..) | If(..) | Loop(..) | Match(..) | Struct(..)
50-
| TryBlock(..) | While(..) => break Some(expr),
49+
Gen(..)
50+
| Block(..)
51+
| ForLoop { .. }
52+
| If(..)
53+
| Loop(..)
54+
| Match(..)
55+
| Struct(..)
56+
| TryBlock(..)
57+
| While(..) => break Some(expr),
5158
_ => break None,
5259
}
5360
}

compiler/rustc_ast/src/visit.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -844,11 +844,11 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
844844
visitor.visit_expr(subexpression);
845845
visitor.visit_block(block);
846846
}
847-
ExprKind::ForLoop(pattern, subexpression, block, opt_label) => {
848-
walk_list!(visitor, visit_label, opt_label);
849-
visitor.visit_pat(pattern);
850-
visitor.visit_expr(subexpression);
851-
visitor.visit_block(block);
847+
ExprKind::ForLoop { pat, iter, body, label, is_await: _ } => {
848+
walk_list!(visitor, visit_label, label);
849+
visitor.visit_pat(pat);
850+
visitor.visit_expr(iter);
851+
visitor.visit_block(body);
852852
}
853853
ExprKind::Loop(block, opt_label, _) => {
854854
walk_list!(visitor, visit_label, opt_label);

compiler/rustc_ast_lowering/src/expr.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
5656
return ex;
5757
}
5858
// Desugar `ExprForLoop`
59-
// from: `[opt_ident]: for <pat> in <head> <body>`
59+
// from: `[opt_ident]: for await? <pat> in <iter> <body>`
6060
//
6161
// This also needs special handling because the HirId of the returned `hir::Expr` will not
62-
// correspond to the `e.id`, so `lower_expr_for` handles attribute lowering itself.
63-
ExprKind::ForLoop(pat, head, body, opt_label) => {
64-
return self.lower_expr_for(e, pat, head, body, *opt_label);
62+
// correspond to the `e.id`, so `lower_expr_for` handles attribute low}ering itself.
63+
ExprKind::ForLoop { pat, iter, body, label, is_await } => {
64+
return self.lower_expr_for(e, pat, iter, body, *label, *is_await);
6565
}
6666
_ => (),
6767
}
@@ -331,7 +331,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
331331
),
332332
ExprKind::Try(sub_expr) => self.lower_expr_try(e.span, sub_expr),
333333

334-
ExprKind::Paren(_) | ExprKind::ForLoop(..) => {
334+
ExprKind::Paren(_) | ExprKind::ForLoop{..} => {
335335
unreachable!("already handled")
336336
}
337337

@@ -1554,6 +1554,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
15541554
head: &Expr,
15551555
body: &Block,
15561556
opt_label: Option<Label>,
1557+
_is_await: bool,
15571558
) -> hir::Expr<'hir> {
15581559
let head = self.lower_expr_mut(head);
15591560
let pat = self.lower_pat(pat);

compiler/rustc_ast_pretty/src/pprust/state/expr.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -370,20 +370,23 @@ impl<'a> State<'a> {
370370
self.space();
371371
self.print_block_with_attrs(blk, attrs);
372372
}
373-
ast::ExprKind::ForLoop(pat, iter, blk, opt_label) => {
374-
if let Some(label) = opt_label {
373+
ast::ExprKind::ForLoop { pat, iter, body, label, is_await } => {
374+
if let Some(label) = label {
375375
self.print_ident(label.ident);
376376
self.word_space(":");
377377
}
378378
self.cbox(0);
379379
self.ibox(0);
380380
self.word_nbsp("for");
381+
if *is_await {
382+
self.word_nbsp("await");
383+
}
381384
self.print_pat(pat);
382385
self.space();
383386
self.word_space("in");
384387
self.print_expr_as_cond(iter);
385388
self.space();
386-
self.print_block_with_attrs(blk, attrs);
389+
self.print_block_with_attrs(body, attrs);
387390
}
388391
ast::ExprKind::Loop(blk, opt_label, _) => {
389392
if let Some(label) = opt_label {

compiler/rustc_builtin_macros/src/assert/context.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
303303
| ExprKind::Continue(_)
304304
| ExprKind::Err
305305
| ExprKind::Field(_, _)
306-
| ExprKind::ForLoop(_, _, _, _)
306+
| ExprKind::ForLoop {..}
307307
| ExprKind::FormatArgs(_)
308308
| ExprKind::IncludedBytes(..)
309309
| ExprKind::InlineAsm(_)

compiler/rustc_lint/src/unused.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -852,8 +852,8 @@ trait UnusedDelimLint {
852852
(cond, UnusedDelimsCtx::WhileCond, true, Some(left), Some(right), true)
853853
}
854854

855-
ForLoop(_, ref cond, ref block, ..) => {
856-
(cond, UnusedDelimsCtx::ForIterExpr, true, None, Some(block.span.lo()), true)
855+
ForLoop { ref iter, ref body, .. } => {
856+
(iter, UnusedDelimsCtx::ForIterExpr, true, None, Some(body.span.lo()), true)
857857
}
858858

859859
Match(ref head, _) if Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX => {
@@ -1085,7 +1085,7 @@ impl EarlyLintPass for UnusedParens {
10851085
}
10861086

10871087
match e.kind {
1088-
ExprKind::Let(ref pat, _, _, _) | ExprKind::ForLoop(ref pat, ..) => {
1088+
ExprKind::Let(ref pat, _, _, _) | ExprKind::ForLoop { ref pat, .. } => {
10891089
self.check_unused_parens_pat(cx, pat, false, false, (true, true));
10901090
}
10911091
// We ignore parens in cases like `if (((let Some(0) = Some(1))))` because we already

compiler/rustc_parse/src/parser/expr.rs

+12-5
Original file line numberDiff line numberDiff line change
@@ -1799,7 +1799,7 @@ impl<'a> Parser<'a> {
17991799
&& matches!(
18001800
expr.kind,
18011801
ExprKind::While(_, _, None)
1802-
| ExprKind::ForLoop(_, _, _, None)
1802+
| ExprKind::ForLoop { label: None, .. }
18031803
| ExprKind::Loop(_, None, _)
18041804
| ExprKind::Block(_, None)
18051805
)
@@ -2672,8 +2672,14 @@ impl<'a> Parser<'a> {
26722672
Ok((pat, expr))
26732673
}
26742674

2675-
/// Parses `for <src_pat> in <src_expr> <src_loop_block>` (`for` token already eaten).
2675+
/// Parses `for await? <src_pat> in <src_expr> <src_loop_block>` (`for` token already eaten).
26762676
fn parse_expr_for(&mut self, opt_label: Option<Label>, lo: Span) -> PResult<'a, P<Expr>> {
2677+
let is_await = self.eat_keyword(kw::Await);
2678+
2679+
if is_await {
2680+
self.sess.gated_spans.gate(sym::async_iterator, self.prev_token.span);
2681+
}
2682+
26772683
let (pat, expr) = self.parse_for_head()?;
26782684
// Recover from missing expression in `for` loop
26792685
if matches!(expr.kind, ExprKind::Block(..))
@@ -2686,13 +2692,14 @@ impl<'a> Parser<'a> {
26862692
let block = self.mk_block(thin_vec![], BlockCheckMode::Default, self.prev_token.span);
26872693
return Ok(self.mk_expr(
26882694
lo.to(self.prev_token.span),
2689-
ExprKind::ForLoop(pat, err_expr, block, opt_label),
2695+
ExprKind::ForLoop { pat, iter: err_expr, body: block, label: opt_label, is_await },
26902696
));
26912697
}
26922698

26932699
let (attrs, loop_block) = self.parse_inner_attrs_and_block()?;
26942700

2695-
let kind = ExprKind::ForLoop(pat, expr, loop_block, opt_label);
2701+
let kind =
2702+
ExprKind::ForLoop { pat, iter: expr, body: loop_block, label: opt_label, is_await };
26962703

26972704
self.recover_loop_else("for", lo)?;
26982705

@@ -3770,7 +3777,7 @@ impl MutVisitor for CondChecker<'_> {
37703777
| ExprKind::Lit(_)
37713778
| ExprKind::If(_, _, _)
37723779
| ExprKind::While(_, _, _)
3773-
| ExprKind::ForLoop(_, _, _, _)
3780+
| ExprKind::ForLoop { .. }
37743781
| ExprKind::Loop(_, _, _)
37753782
| ExprKind::Match(_, _)
37763783
| ExprKind::Closure(_)

compiler/rustc_resolve/src/late.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -4246,11 +4246,11 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
42464246
});
42474247
}
42484248

4249-
ExprKind::ForLoop(ref pat, ref iter_expr, ref block, label) => {
4250-
self.visit_expr(iter_expr);
4249+
ExprKind::ForLoop { ref pat, ref iter, ref body, label, is_await: _ } => {
4250+
self.visit_expr(iter);
42514251
self.with_rib(ValueNS, RibKind::Normal, |this| {
42524252
this.resolve_pattern_top(pat, PatternSource::For);
4253-
this.resolve_labeled_block(label, expr.id, block);
4253+
this.resolve_labeled_block(label, expr.id, body);
42544254
});
42554255
}
42564256

compiler/rustc_resolve/src/late/diagnostics.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1409,7 +1409,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
14091409
| ExprKind::Unary(..)
14101410
| ExprKind::If(..)
14111411
| ExprKind::While(..)
1412-
| ExprKind::ForLoop(..)
1412+
| ExprKind::ForLoop { .. }
14131413
| ExprKind::Match(..),
14141414
..
14151415
}),

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,7 @@ symbols! {
423423
async_closure,
424424
async_fn_in_trait,
425425
async_fn_track_caller,
426+
async_iterator,
426427
atomic,
427428
atomic_mod,
428429
atomics,

src/tools/clippy/clippy_lints/src/needless_continue.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,11 @@ where
220220
F: FnMut(&ast::Block, Option<&ast::Label>),
221221
{
222222
if let ast::ExprKind::While(_, loop_block, label)
223-
| ast::ExprKind::ForLoop(_, _, loop_block, label)
223+
| ast::ExprKind::ForLoop {
224+
body: loop_block,
225+
label,
226+
..
227+
}
224228
| ast::ExprKind::Loop(loop_block, label, ..) = &expr.kind
225229
{
226230
func(loop_block, label.as_ref());

src/tools/clippy/clippy_lints/src/redundant_else.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ impl<'ast> Visitor<'ast> for BreakVisitor {
111111
ExprKind::If(_, ref then, Some(ref els)) => self.check_block(then) && self.check_expr(els),
112112
ExprKind::If(_, _, None)
113113
// ignore loops for simplicity
114-
| ExprKind::While(..) | ExprKind::ForLoop(..) | ExprKind::Loop(..) => false,
114+
| ExprKind::While(..) | ExprKind::ForLoop { .. } | ExprKind::Loop(..) => false,
115115
_ => {
116116
walk_expr(self, expr);
117117
return;

src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,7 @@ fn ident_difference_expr_with_base_location(
554554
| (Closure(_), Closure(_))
555555
| (Match(_, _), Match(_, _))
556556
| (Loop(_, _, _), Loop(_, _, _))
557-
| (ForLoop(_, _, _, _), ForLoop(_, _, _, _))
557+
| (ForLoop { .. }, ForLoop { .. })
558558
| (While(_, _, _), While(_, _, _))
559559
| (If(_, _, _), If(_, _, _))
560560
| (Let(_, _, _, _), Let(_, _, _, _))

src/tools/clippy/clippy_utils/src/ast_utils.rs

+16-3
Original file line numberDiff line numberDiff line change
@@ -169,9 +169,22 @@ pub fn eq_expr(l: &Expr, r: &Expr) -> bool {
169169
(Let(lp, le, _, _), Let(rp, re, _, _)) => eq_pat(lp, rp) && eq_expr(le, re),
170170
(If(lc, lt, le), If(rc, rt, re)) => eq_expr(lc, rc) && eq_block(lt, rt) && eq_expr_opt(le, re),
171171
(While(lc, lt, ll), While(rc, rt, rl)) => eq_label(ll, rl) && eq_expr(lc, rc) && eq_block(lt, rt),
172-
(ForLoop(lp, li, lt, ll), ForLoop(rp, ri, rt, rl)) => {
173-
eq_label(ll, rl) && eq_pat(lp, rp) && eq_expr(li, ri) && eq_block(lt, rt)
174-
},
172+
(
173+
ForLoop {
174+
pat: lp,
175+
iter: li,
176+
body: lt,
177+
label: ll,
178+
is_await: la,
179+
},
180+
ForLoop {
181+
pat: rp,
182+
iter: ri,
183+
body: rt,
184+
label: rl,
185+
is_await: ra,
186+
},
187+
) => eq_label(ll, rl) && eq_pat(lp, rp) && eq_expr(li, ri) && eq_block(lt, rt) && la == ra,
175188
(Loop(lt, ll, _), Loop(rt, rl, _)) => eq_label(ll, rl) && eq_block(lt, rt),
176189
(Block(lb, ll), Block(rb, rl)) => eq_label(ll, rl) && eq_block(lb, rb),
177190
(TryBlock(l), TryBlock(r)) => eq_block(l, r),

src/tools/clippy/clippy_utils/src/sugg.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ impl<'a> Sugg<'a> {
197197
| ast::ExprKind::Continue(..)
198198
| ast::ExprKind::Yield(..)
199199
| ast::ExprKind::Field(..)
200-
| ast::ExprKind::ForLoop(..)
200+
| ast::ExprKind::ForLoop { .. }
201201
| ast::ExprKind::Index(..)
202202
| ast::ExprKind::InlineAsm(..)
203203
| ast::ExprKind::OffsetOf(..)

src/tools/rustfmt/src/closures.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ fn is_block_closure_forced(context: &RewriteContext<'_>, expr: &ast::Expr) -> bo
438438

439439
fn is_block_closure_forced_inner(expr: &ast::Expr, version: Version) -> bool {
440440
match expr.kind {
441-
ast::ExprKind::If(..) | ast::ExprKind::While(..) | ast::ExprKind::ForLoop(..) => true,
441+
ast::ExprKind::If(..) | ast::ExprKind::While(..) | ast::ExprKind::ForLoop { .. } => true,
442442
ast::ExprKind::Loop(..) if version == Version::Two => true,
443443
ast::ExprKind::AddrOf(_, _, ref expr)
444444
| ast::ExprKind::Try(ref expr)
@@ -463,7 +463,7 @@ fn expr_requires_semi_to_be_stmt(e: &ast::Expr) -> bool {
463463
| ast::ExprKind::Block(..)
464464
| ast::ExprKind::While(..)
465465
| ast::ExprKind::Loop(..)
466-
| ast::ExprKind::ForLoop(..)
466+
| ast::ExprKind::ForLoop{ ..}
467467
| ast::ExprKind::TryBlock(..) => false,
468468
_ => true,
469469
}

src/tools/rustfmt/src/expr.rs

+13-6
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ pub(crate) fn format_expr(
134134
}
135135
ast::ExprKind::Let(ref pat, ref expr, _span, _) => rewrite_let(context, shape, pat, expr),
136136
ast::ExprKind::If(..)
137-
| ast::ExprKind::ForLoop(..)
137+
| ast::ExprKind::ForLoop { .. }
138138
| ast::ExprKind::Loop(..)
139139
| ast::ExprKind::While(..) => to_control_flow(expr, expr_type)
140140
.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<
682682
expr.span,
683683
))
684684
}
685-
ast::ExprKind::ForLoop(ref pat, ref cond, ref block, label) => {
686-
Some(ControlFlow::new_for(pat, cond, block, label, expr.span))
687-
}
685+
ast::ExprKind::ForLoop {
686+
ref pat,
687+
ref iter,
688+
ref body,
689+
label,
690+
is_await,
691+
} => Some(ControlFlow::new_for(
692+
pat, iter, body, label, expr.span, is_await,
693+
)),
688694
ast::ExprKind::Loop(ref block, label, _) => {
689695
Some(ControlFlow::new_loop(block, label, expr.span))
690696
}
@@ -771,14 +777,15 @@ impl<'a> ControlFlow<'a> {
771777
block: &'a ast::Block,
772778
label: Option<ast::Label>,
773779
span: Span,
780+
is_await: bool,
774781
) -> ControlFlow<'a> {
775782
ControlFlow {
776783
cond: Some(cond),
777784
block,
778785
else_block: None,
779786
label,
780787
pat: Some(pat),
781-
keyword: "for",
788+
keyword: if is_await { "for await" } else { "for" },
782789
matcher: "",
783790
connector: " in",
784791
allow_single_line: false,
@@ -1364,7 +1371,7 @@ pub(crate) fn can_be_overflowed_expr(
13641371
|| context.config.overflow_delimited_expr()
13651372
}
13661373
ast::ExprKind::If(..)
1367-
| ast::ExprKind::ForLoop(..)
1374+
| ast::ExprKind::ForLoop { .. }
13681375
| ast::ExprKind::Loop(..)
13691376
| ast::ExprKind::While(..) => {
13701377
context.config.combine_control_expr() && context.use_block_indent() && args_len == 1

src/tools/rustfmt/src/matches.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,7 @@ fn can_flatten_block_around_this(body: &ast::Expr) -> bool {
591591
ast::ExprKind::If(..) => false,
592592
// We do not allow collapsing a block around expression with condition
593593
// to avoid it being cluttered with match arm.
594-
ast::ExprKind::ForLoop(..) | ast::ExprKind::While(..) => false,
594+
ast::ExprKind::ForLoop { .. } | ast::ExprKind::While(..) => false,
595595
ast::ExprKind::Loop(..)
596596
| ast::ExprKind::Match(..)
597597
| ast::ExprKind::Block(..)

0 commit comments

Comments
 (0)