Skip to content

Commit a5b0dc3

Browse files
Rewrite closure-of-async to async-closure
1 parent 8fe0c75 commit a5b0dc3

File tree

3 files changed

+76
-39
lines changed

3 files changed

+76
-39
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1215,6 +1215,30 @@ impl Expr {
12151215
}
12161216
}
12171217

1218+
pub fn peel_uwu(&self) -> &Expr {
1219+
let mut expr = self;
1220+
loop {
1221+
match &expr.kind {
1222+
ExprKind::Block(blk, None) => {
1223+
if blk.stmts.len() == 1
1224+
&& let StmtKind::Expr(blk) = &blk.stmts[0].kind
1225+
{
1226+
expr = blk;
1227+
} else {
1228+
break;
1229+
}
1230+
}
1231+
ExprKind::Paren(paren) => {
1232+
expr = paren;
1233+
}
1234+
_ => {
1235+
break;
1236+
}
1237+
}
1238+
}
1239+
expr
1240+
}
1241+
12181242
pub fn peel_parens(&self) -> &Expr {
12191243
let mut expr = self;
12201244
while let ExprKind::Paren(inner) = &expr.kind {
@@ -1615,15 +1639,15 @@ pub struct QSelf {
16151639
}
16161640

16171641
/// A capture clause used in closures and `async` blocks.
1618-
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
1642+
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic, Ord, PartialOrd)]
16191643
pub enum CaptureBy {
1644+
/// `move` keyword was not specified.
1645+
Ref,
16201646
/// `move |x| y + x`.
16211647
Value {
16221648
/// The span of the `move` keyword.
16231649
move_kw: Span,
16241650
},
1625-
/// `move` keyword was not specified.
1626-
Ref,
16271651
}
16281652

16291653
/// Closure lifetime binder, `for<'a, 'b>` in `for<'a, 'b> |_: &'a (), _: &'b ()|`.

compiler/rustc_ast_lowering/src/expr.rs

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -218,18 +218,53 @@ impl<'hir> LoweringContext<'_, 'hir> {
218218
*fn_decl_span,
219219
*fn_arg_span,
220220
),
221-
None => self.lower_expr_closure(
222-
binder,
223-
*capture_clause,
224-
e.id,
225-
hir_id,
226-
*constness,
227-
*movability,
228-
fn_decl,
229-
body,
230-
*fn_decl_span,
231-
*fn_arg_span,
232-
),
221+
None => {
222+
let peeled = body.peel_uwu();
223+
if let ast::ExprKind::Gen(
224+
gen_capture_clause,
225+
block,
226+
gen_kind @ ast::GenBlockKind::Async,
227+
span,
228+
) = &peeled.kind
229+
{
230+
let coroutine_kind = match gen_kind {
231+
GenBlockKind::Async => CoroutineKind::Async { span: *span, closure_id: peeled.node_id(), return_impl_trait_id: self.next_node_id() },
232+
GenBlockKind::Gen => CoroutineKind::Gen { span: *span, closure_id: peeled.node_id(), return_impl_trait_id: self.next_node_id() },
233+
GenBlockKind::AsyncGen => CoroutineKind::AsyncGen { span: *span, closure_id: peeled.node_id(), return_impl_trait_id: self.next_node_id() },
234+
};
235+
let id = self.next_node_id();
236+
self.lower_expr_coroutine_closure(
237+
binder,
238+
capture_clause.max(*gen_capture_clause),
239+
e.id,
240+
hir_id,
241+
coroutine_kind,
242+
fn_decl,
243+
&ast::Expr {
244+
id,
245+
span: *span,
246+
kind: ExprKind::Block(block.clone(), None),
247+
attrs: thin_vec![],
248+
tokens: None,
249+
},
250+
*fn_decl_span,
251+
*fn_arg_span,
252+
)
253+
} else {
254+
self.lower_expr_closure(
255+
binder,
256+
*capture_clause,
257+
e.id,
258+
hir_id,
259+
*constness,
260+
*movability,
261+
fn_decl,
262+
body,
263+
*fn_decl_span,
264+
*fn_arg_span,
265+
)
266+
}
267+
}
233268
},
234269
ExprKind::Gen(capture_clause, block, genblock_kind, decl_span) => {
235270
let desugaring_kind = match genblock_kind {
Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,3 @@
1-
error[E0525]: expected a closure that implements the `async Fn` trait, but this closure only implements `async FnOnce`
2-
--> $DIR/wrong-fn-kind.rs:17:20
3-
|
4-
LL | needs_async_fn(move || async move {
5-
| -------------- -^^^^^^
6-
| | |
7-
| _____|______________this closure implements `async FnOnce`, not `async Fn`
8-
| | |
9-
| | required by a bound introduced by this call
10-
LL | |
11-
LL | | println!("{x}");
12-
| | - closure is `async FnOnce` because it moves the variable `x` out of its environment
13-
LL | | });
14-
| |_____- the requirement to implement `async Fn` derives from here
15-
|
16-
note: required by a bound in `needs_async_fn`
17-
--> $DIR/wrong-fn-kind.rs:5:27
18-
|
19-
LL | fn needs_async_fn(_: impl async Fn()) {}
20-
| ^^^^^^^^^^ required by this bound in `needs_async_fn`
21-
221
error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure
232
--> $DIR/wrong-fn-kind.rs:9:20
243
|
@@ -35,7 +14,6 @@ LL |
3514
LL | x += 1;
3615
| - mutable borrow occurs due to use of `x` in closure
3716

38-
error: aborting due to 2 previous errors
17+
error: aborting due to 1 previous error
3918

40-
Some errors have detailed explanations: E0525, E0596.
41-
For more information about an error, try `rustc --explain E0525`.
19+
For more information about this error, try `rustc --explain E0596`.

0 commit comments

Comments
 (0)