Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 8120660

Browse files
committedNov 18, 2022
Avoid GenFuture shim when compiling async constructs
Previously, async constructs would be lowered to "normal" generators, with an additional `from_generator` / `GenFuture` shim in between to convert from `Generator` to `Future`. The compiler will now special-case these generators internally so that async constructs will *directly* implement `Future` without the need to go through the `from_generator` / `GenFuture` shim. The primary motivation for this change was hiding this implementation detail in stack traces and debuginfo, but it can in theory also help the optimizer as there is less abstractions to see through.
1 parent 9d46c7a commit 8120660

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+427
-441
lines changed
 

‎compiler/rustc_ast_lowering/src/expr.rs

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -148,15 +148,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
148148
self.arena.alloc_from_iter(arms.iter().map(|x| self.lower_arm(x))),
149149
hir::MatchSource::Normal,
150150
),
151-
ExprKind::Async(capture_clause, closure_node_id, ref block) => self
152-
.make_async_expr(
151+
ExprKind::Async(capture_clause, closure_node_id, ref block) => {
152+
return self.make_async_expr(
153153
capture_clause,
154154
closure_node_id,
155155
None,
156-
block.span,
156+
e.span,
157157
hir::AsyncGeneratorKind::Block,
158158
|this| this.with_new_scopes(|this| this.lower_block_expr(block)),
159-
),
159+
);
160+
}
160161
ExprKind::Await(ref expr) => {
161162
let dot_await_span = if expr.span.hi() < e.span.hi() {
162163
let span_with_whitespace = self
@@ -575,14 +576,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
575576
}
576577
}
577578

578-
/// Lower an `async` construct to a generator that is then wrapped so it implements `Future`.
579+
/// Lower an `async` construct to a generator that implements `Future`.
579580
///
580581
/// This results in:
581582
///
582583
/// ```text
583-
/// std::future::from_generator(static move? |_task_context| -> <ret_ty> {
584+
/// static move? |_task_context| -> <ret_ty> {
584585
/// <body>
585-
/// })
586+
/// }
586587
/// ```
587588
pub(super) fn make_async_expr(
588589
&mut self,
@@ -592,20 +593,22 @@ impl<'hir> LoweringContext<'_, 'hir> {
592593
span: Span,
593594
async_gen_kind: hir::AsyncGeneratorKind,
594595
body: impl FnOnce(&mut Self) -> hir::Expr<'hir>,
595-
) -> hir::ExprKind<'hir> {
596+
) -> hir::Expr<'hir> {
596597
let output = match ret_ty {
597598
Some(ty) => hir::FnRetTy::Return(
598599
self.lower_ty(&ty, &ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock)),
599600
),
600601
None => hir::FnRetTy::DefaultReturn(self.lower_span(span)),
601602
};
602603

603-
// Resume argument type. We let the compiler infer this to simplify the lowering. It is
604-
// fully constrained by `future::from_generator`.
604+
// Resume argument type: `ResumeTy`
605+
let unstable_span =
606+
self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone());
607+
let resume_ty = hir::QPath::LangItem(hir::LangItem::ResumeTy, unstable_span, None);
605608
let input_ty = hir::Ty {
606609
hir_id: self.next_id(),
607-
kind: hir::TyKind::Infer,
608-
span: self.lower_span(span),
610+
kind: hir::TyKind::Path(resume_ty),
611+
span: unstable_span,
609612
};
610613

611614
// The closure/generator `FnDecl` takes a single (resume) argument of type `input_ty`.
@@ -688,16 +691,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
688691

689692
let generator = hir::Expr { hir_id, kind: generator_kind, span: self.lower_span(span) };
690693

691-
// `future::from_generator`:
692-
let gen_future = self.expr_lang_item_path(
693-
unstable_span,
694-
hir::LangItem::FromGenerator,
695-
AttrVec::new(),
696-
None,
697-
);
698-
699-
// `future::from_generator(generator)`:
700-
hir::ExprKind::Call(self.arena.alloc(gen_future), arena_vec![self; generator])
694+
generator
701695
}
702696

703697
/// Desugar `<expr>.await` into:
@@ -1001,7 +995,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
1001995
}
1002996

1003997
// Transform `async |x: u8| -> X { ... }` into
1004-
// `|x: u8| future_from_generator(|| -> X { ... })`.
998+
// `|x: u8| || -> X { ... }`.
1005999
let body_id = this.lower_fn_body(&outer_decl, |this| {
10061000
let async_ret_ty =
10071001
if let FnRetTy::Ty(ty) = &decl.output { Some(ty.clone()) } else { None };
@@ -1013,7 +1007,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
10131007
hir::AsyncGeneratorKind::Closure,
10141008
|this| this.with_new_scopes(|this| this.lower_expr_mut(body)),
10151009
);
1016-
this.expr(fn_decl_span, async_body, AttrVec::new())
1010+
async_body
10171011
});
10181012
body_id
10191013
});

‎compiler/rustc_ast_lowering/src/item.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1251,10 +1251,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
12511251
},
12521252
);
12531253

1254-
(
1255-
this.arena.alloc_from_iter(parameters),
1256-
this.expr(body.span, async_expr, AttrVec::new()),
1257-
)
1254+
(this.arena.alloc_from_iter(parameters), async_expr)
12581255
})
12591256
}
12601257

0 commit comments

Comments
 (0)