Skip to content

Commit e450dca

Browse files
committed
lowering: move lower_await -> expr.rs
1 parent 548e309 commit e450dca

File tree

2 files changed

+160
-163
lines changed

2 files changed

+160
-163
lines changed

src/librustc/hir/lowering.rs

Lines changed: 0 additions & 162 deletions
Original file line numberDiff line numberDiff line change
@@ -5125,168 +5125,6 @@ impl<'a> LoweringContext<'a> {
51255125
ThinVec::new()));
51265126
P(self.expr_call(e.span, from_err, hir_vec![e]))
51275127
}
5128-
5129-
fn lower_await(
5130-
&mut self,
5131-
await_span: Span,
5132-
expr: &ast::Expr,
5133-
) -> hir::ExprKind {
5134-
// to:
5135-
//
5136-
// {
5137-
// let mut pinned = <expr>;
5138-
// loop {
5139-
// match ::std::future::poll_with_tls_context(unsafe {
5140-
// ::std::pin::Pin::new_unchecked(&mut pinned)
5141-
// }) {
5142-
// ::std::task::Poll::Ready(result) => break result,
5143-
// ::std::task::Poll::Pending => {},
5144-
// }
5145-
// yield ();
5146-
// }
5147-
// }
5148-
match self.generator_kind {
5149-
Some(hir::GeneratorKind::Async) => {},
5150-
Some(hir::GeneratorKind::Gen) |
5151-
None => {
5152-
let mut err = struct_span_err!(
5153-
self.sess,
5154-
await_span,
5155-
E0728,
5156-
"`await` is only allowed inside `async` functions and blocks"
5157-
);
5158-
err.span_label(await_span, "only allowed inside `async` functions and blocks");
5159-
if let Some(item_sp) = self.current_item {
5160-
err.span_label(item_sp, "this is not `async`");
5161-
}
5162-
err.emit();
5163-
}
5164-
}
5165-
let span = self.mark_span_with_reason(
5166-
DesugaringKind::Await,
5167-
await_span,
5168-
None,
5169-
);
5170-
let gen_future_span = self.mark_span_with_reason(
5171-
DesugaringKind::Await,
5172-
await_span,
5173-
self.allow_gen_future.clone(),
5174-
);
5175-
5176-
// let mut pinned = <expr>;
5177-
let expr = P(self.lower_expr(expr));
5178-
let pinned_ident = Ident::with_empty_ctxt(sym::pinned);
5179-
let (pinned_pat, pinned_pat_hid) = self.pat_ident_binding_mode(
5180-
span,
5181-
pinned_ident,
5182-
hir::BindingAnnotation::Mutable,
5183-
);
5184-
let pinned_let = self.stmt_let_pat(
5185-
ThinVec::new(),
5186-
span,
5187-
Some(expr),
5188-
pinned_pat,
5189-
hir::LocalSource::AwaitDesugar,
5190-
);
5191-
5192-
// ::std::future::poll_with_tls_context(unsafe {
5193-
// ::std::pin::Pin::new_unchecked(&mut pinned)
5194-
// })`
5195-
let poll_expr = {
5196-
let pinned = P(self.expr_ident(span, pinned_ident, pinned_pat_hid));
5197-
let ref_mut_pinned = self.expr_mut_addr_of(span, pinned);
5198-
let pin_ty_id = self.next_id();
5199-
let new_unchecked_expr_kind = self.expr_call_std_assoc_fn(
5200-
pin_ty_id,
5201-
span,
5202-
&[sym::pin, sym::Pin],
5203-
"new_unchecked",
5204-
hir_vec![ref_mut_pinned],
5205-
);
5206-
let new_unchecked = P(self.expr(span, new_unchecked_expr_kind, ThinVec::new()));
5207-
let unsafe_expr = self.expr_unsafe(new_unchecked);
5208-
P(self.expr_call_std_path(
5209-
gen_future_span,
5210-
&[sym::future, sym::poll_with_tls_context],
5211-
hir_vec![unsafe_expr],
5212-
))
5213-
};
5214-
5215-
// `::std::task::Poll::Ready(result) => break result`
5216-
let loop_node_id = self.sess.next_node_id();
5217-
let loop_hir_id = self.lower_node_id(loop_node_id);
5218-
let ready_arm = {
5219-
let x_ident = Ident::with_empty_ctxt(sym::result);
5220-
let (x_pat, x_pat_hid) = self.pat_ident(span, x_ident);
5221-
let x_expr = P(self.expr_ident(span, x_ident, x_pat_hid));
5222-
let ready_pat = self.pat_std_enum(
5223-
span,
5224-
&[sym::task, sym::Poll, sym::Ready],
5225-
hir_vec![x_pat],
5226-
);
5227-
let break_x = self.with_loop_scope(loop_node_id, |this| {
5228-
let expr_break = hir::ExprKind::Break(
5229-
this.lower_loop_destination(None),
5230-
Some(x_expr),
5231-
);
5232-
P(this.expr(await_span, expr_break, ThinVec::new()))
5233-
});
5234-
self.arm(hir_vec![ready_pat], break_x)
5235-
};
5236-
5237-
// `::std::task::Poll::Pending => {}`
5238-
let pending_arm = {
5239-
let pending_pat = self.pat_std_enum(
5240-
span,
5241-
&[sym::task, sym::Poll, sym::Pending],
5242-
hir_vec![],
5243-
);
5244-
let empty_block = P(self.expr_block_empty(span));
5245-
self.arm(hir_vec![pending_pat], empty_block)
5246-
};
5247-
5248-
let match_stmt = {
5249-
let match_expr = self.expr_match(
5250-
span,
5251-
poll_expr,
5252-
hir_vec![ready_arm, pending_arm],
5253-
hir::MatchSource::AwaitDesugar,
5254-
);
5255-
self.stmt_expr(span, match_expr)
5256-
};
5257-
5258-
let yield_stmt = {
5259-
let unit = self.expr_unit(span);
5260-
let yield_expr = self.expr(
5261-
span,
5262-
hir::ExprKind::Yield(P(unit), hir::YieldSource::Await),
5263-
ThinVec::new(),
5264-
);
5265-
self.stmt_expr(span, yield_expr)
5266-
};
5267-
5268-
let loop_block = P(self.block_all(
5269-
span,
5270-
hir_vec![match_stmt, yield_stmt],
5271-
None,
5272-
));
5273-
5274-
let loop_expr = P(hir::Expr {
5275-
hir_id: loop_hir_id,
5276-
node: hir::ExprKind::Loop(
5277-
loop_block,
5278-
None,
5279-
hir::LoopSource::Loop,
5280-
),
5281-
span,
5282-
attrs: ThinVec::new(),
5283-
});
5284-
5285-
hir::ExprKind::Block(
5286-
P(self.block_all(span, hir_vec![pinned_let], Some(loop_expr))),
5287-
None,
5288-
)
5289-
}
52905128
}
52915129

52925130
fn body_ids(bodies: &BTreeMap<hir::BodyId, hir::Body>) -> Vec<hir::BodyId> {

src/librustc/hir/lowering/expr.rs

Lines changed: 160 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ impl LoweringContext<'_> {
263263
})
264264
})
265265
}
266-
ExprKind::Await(ref expr) => self.lower_await(e.span, expr),
266+
ExprKind::Await(ref expr) => self.lower_expr_await(e.span, expr),
267267
ExprKind::Closure(
268268
capture_clause, asyncness, movability, ref decl, ref body, fn_decl_span
269269
) => if let IsAsync::Async { closure_id, .. } = asyncness {
@@ -375,6 +375,165 @@ impl LoweringContext<'_> {
375375
}
376376
}
377377

378+
/// Desugar `<expr>.await` into:
379+
/// ```rust
380+
/// {
381+
/// let mut pinned = <expr>;
382+
/// loop {
383+
/// match ::std::future::poll_with_tls_context(unsafe {
384+
/// ::std::pin::Pin::new_unchecked(&mut pinned)
385+
/// }) {
386+
/// ::std::task::Poll::Ready(result) => break result,
387+
/// ::std::task::Poll::Pending => {},
388+
/// }
389+
/// yield ();
390+
/// }
391+
/// }
392+
/// ```
393+
fn lower_expr_await(&mut self, await_span: Span, expr: &Expr) -> hir::ExprKind {
394+
match self.generator_kind {
395+
Some(hir::GeneratorKind::Async) => {},
396+
Some(hir::GeneratorKind::Gen) |
397+
None => {
398+
let mut err = struct_span_err!(
399+
self.sess,
400+
await_span,
401+
E0728,
402+
"`await` is only allowed inside `async` functions and blocks"
403+
);
404+
err.span_label(await_span, "only allowed inside `async` functions and blocks");
405+
if let Some(item_sp) = self.current_item {
406+
err.span_label(item_sp, "this is not `async`");
407+
}
408+
err.emit();
409+
}
410+
}
411+
let span = self.mark_span_with_reason(
412+
DesugaringKind::Await,
413+
await_span,
414+
None,
415+
);
416+
let gen_future_span = self.mark_span_with_reason(
417+
DesugaringKind::Await,
418+
await_span,
419+
self.allow_gen_future.clone(),
420+
);
421+
422+
// let mut pinned = <expr>;
423+
let expr = P(self.lower_expr(expr));
424+
let pinned_ident = Ident::with_empty_ctxt(sym::pinned);
425+
let (pinned_pat, pinned_pat_hid) = self.pat_ident_binding_mode(
426+
span,
427+
pinned_ident,
428+
hir::BindingAnnotation::Mutable,
429+
);
430+
let pinned_let = self.stmt_let_pat(
431+
ThinVec::new(),
432+
span,
433+
Some(expr),
434+
pinned_pat,
435+
hir::LocalSource::AwaitDesugar,
436+
);
437+
438+
// ::std::future::poll_with_tls_context(unsafe {
439+
// ::std::pin::Pin::new_unchecked(&mut pinned)
440+
// })`
441+
let poll_expr = {
442+
let pinned = P(self.expr_ident(span, pinned_ident, pinned_pat_hid));
443+
let ref_mut_pinned = self.expr_mut_addr_of(span, pinned);
444+
let pin_ty_id = self.next_id();
445+
let new_unchecked_expr_kind = self.expr_call_std_assoc_fn(
446+
pin_ty_id,
447+
span,
448+
&[sym::pin, sym::Pin],
449+
"new_unchecked",
450+
hir_vec![ref_mut_pinned],
451+
);
452+
let new_unchecked = P(self.expr(span, new_unchecked_expr_kind, ThinVec::new()));
453+
let unsafe_expr = self.expr_unsafe(new_unchecked);
454+
P(self.expr_call_std_path(
455+
gen_future_span,
456+
&[sym::future, sym::poll_with_tls_context],
457+
hir_vec![unsafe_expr],
458+
))
459+
};
460+
461+
// `::std::task::Poll::Ready(result) => break result`
462+
let loop_node_id = self.sess.next_node_id();
463+
let loop_hir_id = self.lower_node_id(loop_node_id);
464+
let ready_arm = {
465+
let x_ident = Ident::with_empty_ctxt(sym::result);
466+
let (x_pat, x_pat_hid) = self.pat_ident(span, x_ident);
467+
let x_expr = P(self.expr_ident(span, x_ident, x_pat_hid));
468+
let ready_pat = self.pat_std_enum(
469+
span,
470+
&[sym::task, sym::Poll, sym::Ready],
471+
hir_vec![x_pat],
472+
);
473+
let break_x = self.with_loop_scope(loop_node_id, |this| {
474+
let expr_break = hir::ExprKind::Break(
475+
this.lower_loop_destination(None),
476+
Some(x_expr),
477+
);
478+
P(this.expr(await_span, expr_break, ThinVec::new()))
479+
});
480+
self.arm(hir_vec![ready_pat], break_x)
481+
};
482+
483+
// `::std::task::Poll::Pending => {}`
484+
let pending_arm = {
485+
let pending_pat = self.pat_std_enum(
486+
span,
487+
&[sym::task, sym::Poll, sym::Pending],
488+
hir_vec![],
489+
);
490+
let empty_block = P(self.expr_block_empty(span));
491+
self.arm(hir_vec![pending_pat], empty_block)
492+
};
493+
494+
let match_stmt = {
495+
let match_expr = self.expr_match(
496+
span,
497+
poll_expr,
498+
hir_vec![ready_arm, pending_arm],
499+
hir::MatchSource::AwaitDesugar,
500+
);
501+
self.stmt_expr(span, match_expr)
502+
};
503+
504+
let yield_stmt = {
505+
let unit = self.expr_unit(span);
506+
let yield_expr = self.expr(
507+
span,
508+
hir::ExprKind::Yield(P(unit), hir::YieldSource::Await),
509+
ThinVec::new(),
510+
);
511+
self.stmt_expr(span, yield_expr)
512+
};
513+
514+
let loop_block = P(self.block_all(
515+
span,
516+
hir_vec![match_stmt, yield_stmt],
517+
None,
518+
));
519+
520+
let loop_expr = P(hir::Expr {
521+
hir_id: loop_hir_id,
522+
node: hir::ExprKind::Loop(
523+
loop_block,
524+
None,
525+
hir::LoopSource::Loop,
526+
),
527+
span,
528+
attrs: ThinVec::new(),
529+
});
530+
531+
hir::ExprKind::Block(
532+
P(self.block_all(span, hir_vec![pinned_let], Some(loop_expr))),
533+
None,
534+
)
535+
}
536+
378537
fn lower_expr_closure(
379538
&mut self,
380539
capture_clause: CaptureBy,

0 commit comments

Comments
 (0)