Skip to content

Commit d4a7567

Browse files
Async closures will move params into the future always
1 parent 4b4bcf4 commit d4a7567

10 files changed

+38
-86
lines changed

compiler/rustc_ast_lowering/messages.ftl

-4
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,6 @@ ast_lowering_assoc_ty_parentheses =
1414
ast_lowering_async_coroutines_not_supported =
1515
`async` coroutines are not yet supported
1616
17-
ast_lowering_async_non_move_closure_not_supported =
18-
`async` non-`move` closures with parameters are not currently supported
19-
.help = consider using `let` statements to manually capture variables by reference before entering an `async move` closure
20-
2117
ast_lowering_att_syntax_only_x86 =
2218
the `att_syntax` option is only supported on x86
2319

compiler/rustc_ast_lowering/src/errors.rs

-8
Original file line numberDiff line numberDiff line change
@@ -145,14 +145,6 @@ pub struct ClosureCannotBeStatic {
145145
pub fn_decl_span: Span,
146146
}
147147

148-
#[derive(Diagnostic, Clone, Copy)]
149-
#[help]
150-
#[diag(ast_lowering_async_non_move_closure_not_supported, code = "E0708")]
151-
pub struct AsyncNonMoveClosureNotSupported {
152-
#[primary_span]
153-
pub fn_decl_span: Span,
154-
}
155-
156148
#[derive(Diagnostic, Clone, Copy)]
157149
#[diag(ast_lowering_functional_record_update_destructuring_assignment)]
158150
pub struct FunctionalRecordUpdateDestructuringAssignment {

compiler/rustc_ast_lowering/src/expr.rs

+15-24
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::errors::{
2-
AsyncCoroutinesNotSupported, AsyncNonMoveClosureNotSupported, AwaitOnlyInAsyncFnAndBlocks,
3-
BaseExpressionDoubleDot, ClosureCannotBeStatic, CoroutineTooManyParameters,
2+
AsyncCoroutinesNotSupported, AwaitOnlyInAsyncFnAndBlocks, BaseExpressionDoubleDot,
3+
ClosureCannotBeStatic, CoroutineTooManyParameters,
44
FunctionalRecordUpdateDestructuringAssignment, InclusiveRangeWithNoEnd, MatchArmWithNoBody,
55
NeverPatternWithBody, NeverPatternWithGuard, NotSupportedForLifetimeBinderAsyncClosure,
66
UnderscoreExprLhsAssign,
@@ -13,7 +13,6 @@ use rustc_ast::*;
1313
use rustc_data_structures::stack::ensure_sufficient_stack;
1414
use rustc_hir as hir;
1515
use rustc_hir::def::{DefKind, Res};
16-
use rustc_middle::span_bug;
1716
use rustc_session::errors::report_lit_error;
1817
use rustc_span::source_map::{respan, Spanned};
1918
use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -1028,51 +1027,43 @@ impl<'hir> LoweringContext<'_, 'hir> {
10281027
fn_decl_span: Span,
10291028
fn_arg_span: Span,
10301029
) -> hir::ExprKind<'hir> {
1031-
let CoroutineKind::Async { closure_id: inner_closure_id, .. } = coroutine_kind else {
1032-
span_bug!(fn_decl_span, "`async gen` and `gen` closures are not supported, yet");
1033-
};
1034-
10351030
if let &ClosureBinder::For { span, .. } = binder {
10361031
self.dcx().emit_err(NotSupportedForLifetimeBinderAsyncClosure { span });
10371032
}
10381033

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

1041-
let outer_decl =
1042-
FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) };
1043-
10441036
let body = self.with_new_scopes(fn_decl_span, |this| {
1045-
// FIXME(cramertj): allow `async` non-`move` closures with arguments.
1046-
if capture_clause == CaptureBy::Ref && !decl.inputs.is_empty() {
1047-
this.dcx().emit_err(AsyncNonMoveClosureNotSupported { fn_decl_span });
1048-
}
1049-
10501037
// Transform `async |x: u8| -> X { ... }` into
10511038
// `|x: u8| || -> X { ... }`.
1052-
let body_id = this.lower_fn_body(&outer_decl, |this| {
1039+
let body_id = this.lower_body(|this| {
10531040
let async_ret_ty = if let FnRetTy::Ty(ty) = &decl.output {
10541041
let itctx = ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock);
10551042
Some(hir::FnRetTy::Return(this.lower_ty(ty, &itctx)))
10561043
} else {
10571044
None
10581045
};
10591046

1060-
let async_body = this.make_desugared_coroutine_expr(
1061-
capture_clause,
1062-
inner_closure_id,
1063-
async_ret_ty,
1047+
let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(
1048+
decl,
1049+
|this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)),
10641050
body.span,
1065-
hir::CoroutineDesugaring::Async,
1051+
coroutine_kind,
10661052
hir::CoroutineSource::Closure,
1067-
|this| this.with_new_scopes(fn_decl_span, |this| this.lower_expr_mut(body)),
1053+
async_ret_ty,
10681054
);
1069-
let hir_id = this.lower_node_id(inner_closure_id);
1055+
1056+
let hir_id = this.lower_node_id(coroutine_kind.closure_id());
10701057
this.maybe_forward_track_caller(body.span, closure_hir_id, hir_id);
1071-
hir::Expr { hir_id, kind: async_body, span: this.lower_span(body.span) }
1058+
1059+
(parameters, expr)
10721060
});
10731061
body_id
10741062
});
10751063

1064+
let outer_decl =
1065+
FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) };
1066+
10761067
let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params);
10771068
// We need to lower the declaration outside the new scope, because we
10781069
// have to conserve the state of being inside a loop condition for the

compiler/rustc_ast_lowering/src/item.rs

+18-11
Original file line numberDiff line numberDiff line change
@@ -1052,9 +1052,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
10521052
self.lower_body(|this| {
10531053
let (parameters, expr) = this.lower_coroutine_body_with_moved_arguments(
10541054
decl,
1055-
body,
1055+
|this| this.lower_block_expr(body),
1056+
body.span,
10561057
coroutine_kind,
1057-
CaptureBy::Value { move_kw: rustc_span::DUMMY_SP },
1058+
hir::CoroutineSource::Fn,
1059+
None,
10581060
);
10591061

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

10681070
/// Lowers a desugared coroutine body after moving all of the arguments
10691071
/// into the body. This makes sure that
1070-
fn lower_coroutine_body_with_moved_arguments(
1072+
pub fn lower_coroutine_body_with_moved_arguments(
10711073
&mut self,
10721074
decl: &FnDecl,
1073-
body: &Block,
1075+
lower_body: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::Expr<'hir>,
1076+
body_span: Span,
10741077
coroutine_kind: CoroutineKind,
1075-
capture_clause: CaptureBy,
1078+
coroutine_source: hir::CoroutineSource,
1079+
return_type_hint: Option<hir::FnRetTy<'hir>>,
10761080
) -> (&'hir [hir::Param<'hir>], hir::Expr<'hir>) {
10771081
let mut parameters: Vec<hir::Param<'_>> = Vec::new();
10781082
let mut statements: Vec<hir::Stmt<'_>> = Vec::new();
@@ -1211,7 +1215,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
12111215

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

12161220
// Transform into `drop-temps { <user-body> }`, an expression:
12171221
let desugared_span =
@@ -1242,19 +1246,22 @@ impl<'hir> LoweringContext<'_, 'hir> {
12421246
};
12431247
let closure_id = coroutine_kind.closure_id();
12441248
let coroutine_expr = self.make_desugared_coroutine_expr(
1245-
capture_clause,
1249+
// FIXME(async_closures): This should only move locals,
1250+
// and not upvars. Capturing closure upvars by ref doesn't
1251+
// work right now anyways, so whatever.
1252+
CaptureBy::Value { move_kw: rustc_span::DUMMY_SP },
12461253
closure_id,
1247-
None,
1248-
body.span,
1254+
return_type_hint,
1255+
body_span,
12491256
desugaring_kind,
1250-
hir::CoroutineSource::Fn,
1257+
coroutine_source,
12511258
mkbody,
12521259
);
12531260

12541261
let expr = hir::Expr {
12551262
hir_id: self.lower_node_id(closure_id),
12561263
kind: coroutine_expr,
1257-
span: self.lower_span(body.span),
1264+
span: self.lower_span(body_span),
12581265
};
12591266

12601267
(self.arena.alloc_from_iter(parameters), expr)

compiler/rustc_error_codes/src/error_codes/E0708.md

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#### Note: this error code is no longer emitted by the compiler.
2+
13
`async` non-`move` closures with parameters are currently not supported.
24

35
Erroneous code example:

tests/ui/async-await/async-borrowck-escaping-closure-error.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
// edition:2018
2+
// check-pass
3+
24
#![feature(async_closure)]
35
fn foo() -> Box<dyn std::future::Future<Output = u32>> {
46
let x = 0u32;
57
Box::new((async || x)())
6-
//~^ ERROR E0373
78
}
89

910
fn main() {

tests/ui/async-await/async-borrowck-escaping-closure-error.stderr

-21
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
// edition:2018
2+
// check-pass
23

34
#![feature(async_closure)]
45

56
fn main() {
67
let _ = async |x: u8| {};
7-
//~^ ERROR `async` non-`move` closures with parameters are not currently supported
88
}

tests/ui/async-await/no-params-non-move-async-closure.stderr

-11
This file was deleted.

tests/ui/suggestions/suggest-on-bare-closure-call.stderr

-5
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,6 @@ LL | let _ = async ||{}();
1818
| ^^--
1919
| |
2020
| call expression requires function
21-
|
22-
help: if you meant to create this closure and immediately call it, surround the closure with parentheses
23-
|
24-
LL | let _ = (async ||{})();
25-
| + +
2621

2722
error: aborting due to 2 previous errors
2823

0 commit comments

Comments
 (0)