lowering: extract lower_expr_async_closure
This commit is contained in:
parent
309bf2fcad
commit
ca19e326a6
1 changed files with 67 additions and 49 deletions
|
@ -268,55 +268,13 @@ impl LoweringContext<'_> {
|
||||||
capture_clause, asyncness, movability, ref decl, ref body, fn_decl_span
|
capture_clause, asyncness, movability, ref decl, ref body, fn_decl_span
|
||||||
) => {
|
) => {
|
||||||
if let IsAsync::Async { closure_id, .. } = asyncness {
|
if let IsAsync::Async { closure_id, .. } = asyncness {
|
||||||
let outer_decl = FnDecl {
|
self.lower_expr_async_closure(
|
||||||
inputs: decl.inputs.clone(),
|
capture_clause,
|
||||||
output: FunctionRetTy::Default(fn_decl_span),
|
closure_id,
|
||||||
c_variadic: false,
|
decl,
|
||||||
};
|
body,
|
||||||
// We need to lower the declaration outside the new scope, because we
|
fn_decl_span,
|
||||||
// have to conserve the state of being inside a loop condition for the
|
)
|
||||||
// closure argument types.
|
|
||||||
let fn_decl = self.lower_fn_decl(&outer_decl, None, false, None);
|
|
||||||
|
|
||||||
self.with_new_scopes(|this| {
|
|
||||||
// FIXME(cramertj): allow `async` non-`move` closures with arguments.
|
|
||||||
if capture_clause == CaptureBy::Ref &&
|
|
||||||
!decl.inputs.is_empty()
|
|
||||||
{
|
|
||||||
struct_span_err!(
|
|
||||||
this.sess,
|
|
||||||
fn_decl_span,
|
|
||||||
E0708,
|
|
||||||
"`async` non-`move` closures with arguments \
|
|
||||||
are not currently supported",
|
|
||||||
)
|
|
||||||
.help("consider using `let` statements to manually capture \
|
|
||||||
variables by reference before entering an \
|
|
||||||
`async move` closure")
|
|
||||||
.emit();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transform `async |x: u8| -> X { ... }` into
|
|
||||||
// `|x: u8| future_from_generator(|| -> X { ... })`.
|
|
||||||
let body_id = this.lower_fn_body(&outer_decl, |this| {
|
|
||||||
let async_ret_ty = if let FunctionRetTy::Ty(ty) = &decl.output {
|
|
||||||
Some(ty.clone())
|
|
||||||
} else { None };
|
|
||||||
let async_body = this.make_async_expr(
|
|
||||||
capture_clause, closure_id, async_ret_ty, body.span,
|
|
||||||
|this| {
|
|
||||||
this.with_new_scopes(|this| this.lower_expr(body))
|
|
||||||
});
|
|
||||||
this.expr(fn_decl_span, async_body, ThinVec::new())
|
|
||||||
});
|
|
||||||
hir::ExprKind::Closure(
|
|
||||||
this.lower_capture_clause(capture_clause),
|
|
||||||
fn_decl,
|
|
||||||
body_id,
|
|
||||||
fn_decl_span,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
// Lower outside new scope to preserve `is_in_loop_condition`.
|
// Lower outside new scope to preserve `is_in_loop_condition`.
|
||||||
let fn_decl = self.lower_fn_decl(decl, None, false, None);
|
let fn_decl = self.lower_fn_decl(decl, None, false, None);
|
||||||
|
@ -449,6 +407,66 @@ impl LoweringContext<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn lower_expr_async_closure(
|
||||||
|
&mut self,
|
||||||
|
capture_clause: CaptureBy,
|
||||||
|
closure_id: NodeId,
|
||||||
|
decl: &FnDecl,
|
||||||
|
body: &Expr,
|
||||||
|
fn_decl_span: Span,
|
||||||
|
) -> hir::ExprKind {
|
||||||
|
let outer_decl = FnDecl {
|
||||||
|
inputs: decl.inputs.clone(),
|
||||||
|
output: FunctionRetTy::Default(fn_decl_span),
|
||||||
|
c_variadic: false,
|
||||||
|
};
|
||||||
|
// We need to lower the declaration outside the new scope, because we
|
||||||
|
// have to conserve the state of being inside a loop condition for the
|
||||||
|
// closure argument types.
|
||||||
|
let fn_decl = self.lower_fn_decl(&outer_decl, None, false, None);
|
||||||
|
|
||||||
|
self.with_new_scopes(|this| {
|
||||||
|
// FIXME(cramertj): allow `async` non-`move` closures with arguments.
|
||||||
|
if capture_clause == CaptureBy::Ref && !decl.inputs.is_empty() {
|
||||||
|
struct_span_err!(
|
||||||
|
this.sess,
|
||||||
|
fn_decl_span,
|
||||||
|
E0708,
|
||||||
|
"`async` non-`move` closures with arguments are not currently supported",
|
||||||
|
)
|
||||||
|
.help(
|
||||||
|
"consider using `let` statements to manually capture \
|
||||||
|
variables by reference before entering an `async move` closure"
|
||||||
|
)
|
||||||
|
.emit();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transform `async |x: u8| -> X { ... }` into
|
||||||
|
// `|x: u8| future_from_generator(|| -> X { ... })`.
|
||||||
|
let body_id = this.lower_fn_body(&outer_decl, |this| {
|
||||||
|
let async_ret_ty = if let FunctionRetTy::Ty(ty) = &decl.output {
|
||||||
|
Some(ty.clone())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
let async_body = this.make_async_expr(
|
||||||
|
capture_clause, closure_id, async_ret_ty, body.span,
|
||||||
|
|this| {
|
||||||
|
this.with_new_scopes(|this| this.lower_expr(body))
|
||||||
|
}
|
||||||
|
);
|
||||||
|
this.expr(fn_decl_span, async_body, ThinVec::new())
|
||||||
|
});
|
||||||
|
hir::ExprKind::Closure(
|
||||||
|
this.lower_capture_clause(capture_clause),
|
||||||
|
fn_decl,
|
||||||
|
body_id,
|
||||||
|
fn_decl_span,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Desugar `<start>..=<end>` into `std::ops::RangeInclusive::new(<start>, <end>)`.
|
/// Desugar `<start>..=<end>` into `std::ops::RangeInclusive::new(<start>, <end>)`.
|
||||||
fn lower_expr_range_closed(&mut self, span: Span, e1: &Expr, e2: &Expr) -> hir::ExprKind {
|
fn lower_expr_range_closed(&mut self, span: Span, e1: &Expr, e2: &Expr) -> hir::ExprKind {
|
||||||
let id = self.next_id();
|
let id = self.next_id();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue