Skip to content

Commit ca19e32

Browse files
committed
lowering: extract lower_expr_async_closure
1 parent 309bf2f commit ca19e32

File tree

1 file changed

+67
-49
lines changed

1 file changed

+67
-49
lines changed

src/librustc/hir/lowering/expr.rs

Lines changed: 67 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -268,55 +268,13 @@ impl LoweringContext<'_> {
268268
capture_clause, asyncness, movability, ref decl, ref body, fn_decl_span
269269
) => {
270270
if let IsAsync::Async { closure_id, .. } = asyncness {
271-
let outer_decl = FnDecl {
272-
inputs: decl.inputs.clone(),
273-
output: FunctionRetTy::Default(fn_decl_span),
274-
c_variadic: false,
275-
};
276-
// We need to lower the declaration outside the new scope, because we
277-
// have to conserve the state of being inside a loop condition for the
278-
// closure argument types.
279-
let fn_decl = self.lower_fn_decl(&outer_decl, None, false, None);
280-
281-
self.with_new_scopes(|this| {
282-
// FIXME(cramertj): allow `async` non-`move` closures with arguments.
283-
if capture_clause == CaptureBy::Ref &&
284-
!decl.inputs.is_empty()
285-
{
286-
struct_span_err!(
287-
this.sess,
288-
fn_decl_span,
289-
E0708,
290-
"`async` non-`move` closures with arguments \
291-
are not currently supported",
292-
)
293-
.help("consider using `let` statements to manually capture \
294-
variables by reference before entering an \
295-
`async move` closure")
296-
.emit();
297-
}
298-
299-
// Transform `async |x: u8| -> X { ... }` into
300-
// `|x: u8| future_from_generator(|| -> X { ... })`.
301-
let body_id = this.lower_fn_body(&outer_decl, |this| {
302-
let async_ret_ty = if let FunctionRetTy::Ty(ty) = &decl.output {
303-
Some(ty.clone())
304-
} else { None };
305-
let async_body = this.make_async_expr(
306-
capture_clause, closure_id, async_ret_ty, body.span,
307-
|this| {
308-
this.with_new_scopes(|this| this.lower_expr(body))
309-
});
310-
this.expr(fn_decl_span, async_body, ThinVec::new())
311-
});
312-
hir::ExprKind::Closure(
313-
this.lower_capture_clause(capture_clause),
314-
fn_decl,
315-
body_id,
316-
fn_decl_span,
317-
None,
318-
)
319-
})
271+
self.lower_expr_async_closure(
272+
capture_clause,
273+
closure_id,
274+
decl,
275+
body,
276+
fn_decl_span,
277+
)
320278
} else {
321279
// Lower outside new scope to preserve `is_in_loop_condition`.
322280
let fn_decl = self.lower_fn_decl(decl, None, false, None);
@@ -449,6 +407,66 @@ impl LoweringContext<'_> {
449407
}
450408
}
451409

410+
fn lower_expr_async_closure(
411+
&mut self,
412+
capture_clause: CaptureBy,
413+
closure_id: NodeId,
414+
decl: &FnDecl,
415+
body: &Expr,
416+
fn_decl_span: Span,
417+
) -> hir::ExprKind {
418+
let outer_decl = FnDecl {
419+
inputs: decl.inputs.clone(),
420+
output: FunctionRetTy::Default(fn_decl_span),
421+
c_variadic: false,
422+
};
423+
// We need to lower the declaration outside the new scope, because we
424+
// have to conserve the state of being inside a loop condition for the
425+
// closure argument types.
426+
let fn_decl = self.lower_fn_decl(&outer_decl, None, false, None);
427+
428+
self.with_new_scopes(|this| {
429+
// FIXME(cramertj): allow `async` non-`move` closures with arguments.
430+
if capture_clause == CaptureBy::Ref && !decl.inputs.is_empty() {
431+
struct_span_err!(
432+
this.sess,
433+
fn_decl_span,
434+
E0708,
435+
"`async` non-`move` closures with arguments are not currently supported",
436+
)
437+
.help(
438+
"consider using `let` statements to manually capture \
439+
variables by reference before entering an `async move` closure"
440+
)
441+
.emit();
442+
}
443+
444+
// Transform `async |x: u8| -> X { ... }` into
445+
// `|x: u8| future_from_generator(|| -> X { ... })`.
446+
let body_id = this.lower_fn_body(&outer_decl, |this| {
447+
let async_ret_ty = if let FunctionRetTy::Ty(ty) = &decl.output {
448+
Some(ty.clone())
449+
} else {
450+
None
451+
};
452+
let async_body = this.make_async_expr(
453+
capture_clause, closure_id, async_ret_ty, body.span,
454+
|this| {
455+
this.with_new_scopes(|this| this.lower_expr(body))
456+
}
457+
);
458+
this.expr(fn_decl_span, async_body, ThinVec::new())
459+
});
460+
hir::ExprKind::Closure(
461+
this.lower_capture_clause(capture_clause),
462+
fn_decl,
463+
body_id,
464+
fn_decl_span,
465+
None,
466+
)
467+
})
468+
}
469+
452470
/// Desugar `<start>..=<end>` into `std::ops::RangeInclusive::new(<start>, <end>)`.
453471
fn lower_expr_range_closed(&mut self, span: Span, e1: &Expr, e2: &Expr) -> hir::ExprKind {
454472
let id = self.next_id();

0 commit comments

Comments
 (0)