Skip to content

Commit

Permalink
Async closures will move params into the future always
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Jan 14, 2024
1 parent 4b4bcf4 commit d4a7567
Show file tree
Hide file tree
Showing 10 changed files with 38 additions and 86 deletions.
4 changes: 0 additions & 4 deletions compiler/rustc_ast_lowering/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@ ast_lowering_assoc_ty_parentheses =
ast_lowering_async_coroutines_not_supported =
`async` coroutines are not yet supported
ast_lowering_async_non_move_closure_not_supported =
`async` non-`move` closures with parameters are not currently supported
.help = consider using `let` statements to manually capture variables by reference before entering an `async move` closure
ast_lowering_att_syntax_only_x86 =
the `att_syntax` option is only supported on x86
Expand Down
8 changes: 0 additions & 8 deletions compiler/rustc_ast_lowering/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,14 +145,6 @@ pub struct ClosureCannotBeStatic {
pub fn_decl_span: Span,
}

#[derive(Diagnostic, Clone, Copy)]
#[help]
#[diag(ast_lowering_async_non_move_closure_not_supported, code = "E0708")]
pub struct AsyncNonMoveClosureNotSupported {
#[primary_span]
pub fn_decl_span: Span,
}

#[derive(Diagnostic, Clone, Copy)]
#[diag(ast_lowering_functional_record_update_destructuring_assignment)]
pub struct FunctionalRecordUpdateDestructuringAssignment {
Expand Down
39 changes: 15 additions & 24 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::errors::{
AsyncCoroutinesNotSupported, AsyncNonMoveClosureNotSupported, AwaitOnlyInAsyncFnAndBlocks,
BaseExpressionDoubleDot, ClosureCannotBeStatic, CoroutineTooManyParameters,
AsyncCoroutinesNotSupported, AwaitOnlyInAsyncFnAndBlocks, BaseExpressionDoubleDot,
ClosureCannotBeStatic, CoroutineTooManyParameters,
FunctionalRecordUpdateDestructuringAssignment, InclusiveRangeWithNoEnd, MatchArmWithNoBody,
NeverPatternWithBody, NeverPatternWithGuard, NotSupportedForLifetimeBinderAsyncClosure,
UnderscoreExprLhsAssign,
Expand All @@ -13,7 +13,6 @@ use rustc_ast::*;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_middle::span_bug;
use rustc_session::errors::report_lit_error;
use rustc_span::source_map::{respan, Spanned};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
Expand Down Expand Up @@ -1028,51 +1027,43 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn_decl_span: Span,
fn_arg_span: Span,
) -> hir::ExprKind<'hir> {
let CoroutineKind::Async { closure_id: inner_closure_id, .. } = coroutine_kind else {
span_bug!(fn_decl_span, "`async gen` and `gen` closures are not supported, yet");
};

if let &ClosureBinder::For { span, .. } = binder {
self.dcx().emit_err(NotSupportedForLifetimeBinderAsyncClosure { span });
}

let (binder_clause, generic_params) = self.lower_closure_binder(binder);

let outer_decl =
FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) };

let body = self.with_new_scopes(fn_decl_span, |this| {
// FIXME(cramertj): allow `async` non-`move` closures with arguments.
if capture_clause == CaptureBy::Ref && !decl.inputs.is_empty() {
this.dcx().emit_err(AsyncNonMoveClosureNotSupported { fn_decl_span });
}

// Transform `async |x: u8| -> X { ... }` into
// `|x: u8| || -> X { ... }`.
let body_id = this.lower_fn_body(&outer_decl, |this| {
let body_id = this.lower_body(|this| {
let async_ret_ty = if let FnRetTy::Ty(ty) = &decl.output {
let itctx = ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock);
Some(hir::FnRetTy::Return(this.lower_ty(ty, &itctx)))
} else {
None
};

let async_body = this.make_desugared_coroutine_expr(
capture_clause,
inner_closure_id,
async_ret_ty,
let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(
decl,
|this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)),
body.span,
hir::CoroutineDesugaring::Async,
coroutine_kind,
hir::CoroutineSource::Closure,
|this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)),
async_ret_ty,
);
let hir_id = this.lower_node_id(inner_closure_id);

let hir_id = this.lower_node_id(coroutine_kind.closure_id());
this.maybe_forward_track_caller(body.span, closure_hir_id, hir_id);
hir::Expr { hir_id, kind: async_body, span: this.lower_span(body.span) }

(parameters, expr)
});
body_id
});

let outer_decl =
FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) };

let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params);
// 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
Expand Down
29 changes: 18 additions & 11 deletions compiler/rustc_ast_lowering/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1052,9 +1052,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
self.lower_body(|this| {
let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(
decl,
body,
|this| this.lower_block_expr(body),
body.span,
coroutine_kind,
CaptureBy::Value { move_kw: rustc_span::DUMMY_SP },
hir::CoroutineSource::Fn,
None,
);

// FIXME(async_fn_track_caller): Can this be moved above?
Expand All @@ -1067,12 +1069,14 @@ impl<'hir> LoweringContext<'_, 'hir> {

/// Lowers a desugared coroutine body after moving all of the arguments
/// into the body. This makes sure that
fn lower_coroutine_body_with_moved_arguments(
pub fn lower_coroutine_body_with_moved_arguments(
&mut self,
decl: &FnDecl,
body: &Block,
lower_body: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::Expr<'hir>,
body_span: Span,
coroutine_kind: CoroutineKind,
capture_clause: CaptureBy,
coroutine_source: hir::CoroutineSource,
return_type_hint: Option<hir::FnRetTy<'hir>>,
) -> (&'hir [hir::Param<'hir>], hir::Expr<'hir>) {
let mut parameters: Vec<hir::Param<'_>> = Vec::new();
let mut statements: Vec<hir::Stmt<'_>> = Vec::new();
Expand Down Expand Up @@ -1211,7 +1215,7 @@ impl<'hir> LoweringContext<'_, 'hir> {

let mkbody = |this: &mut LoweringContext<'_, 'hir>| {
// Create a block from the user's function body:
let user_body = this.lower_block_expr(body);
let user_body = lower_body(this);

// Transform into `drop-temps { <user-body> }`, an expression:
let desugared_span =
Expand Down Expand Up @@ -1242,19 +1246,22 @@ impl<'hir> LoweringContext<'_, 'hir> {
};
let closure_id = coroutine_kind.closure_id();
let coroutine_expr = self.make_desugared_coroutine_expr(
capture_clause,
// FIXME(async_closures): This should only move locals,
// and not upvars. Capturing closure upvars by ref doesn't
// work right now anyways, so whatever.
CaptureBy::Value { move_kw: rustc_span::DUMMY_SP },
closure_id,
None,
body.span,
return_type_hint,
body_span,
desugaring_kind,
hir::CoroutineSource::Fn,
coroutine_source,
mkbody,
);

let expr = hir::Expr {
hir_id: self.lower_node_id(closure_id),
kind: coroutine_expr,
span: self.lower_span(body.span),
span: self.lower_span(body_span),
};

(self.arena.alloc_from_iter(parameters), expr)
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_error_codes/src/error_codes/E0708.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#### Note: this error code is no longer emitted by the compiler.

`async` non-`move` closures with parameters are currently not supported.

Erroneous code example:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
// edition:2018
// check-pass

#![feature(async_closure)]
fn foo() -> Box<dyn std::future::Future<Output = u32>> {
let x = 0u32;
Box::new((async || x)())
//~^ ERROR E0373
}

fn main() {
Expand Down
21 changes: 0 additions & 21 deletions tests/ui/async-await/async-borrowck-escaping-closure-error.stderr

This file was deleted.

2 changes: 1 addition & 1 deletion tests/ui/async-await/no-params-non-move-async-closure.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// edition:2018
// check-pass

#![feature(async_closure)]

fn main() {
let _ = async |x: u8| {};
//~^ ERROR `async` non-`move` closures with parameters are not currently supported
}
11 changes: 0 additions & 11 deletions tests/ui/async-await/no-params-non-move-async-closure.stderr

This file was deleted.

5 changes: 0 additions & 5 deletions tests/ui/suggestions/suggest-on-bare-closure-call.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,6 @@ LL | let _ = async ||{}();
| ^^--
| |
| call expression requires function
|
help: if you meant to create this closure and immediately call it, surround the closure with parentheses
|
LL | let _ = (async ||{})();
| + +

error: aborting due to 2 previous errors

Expand Down

0 comments on commit d4a7567

Please sign in to comment.