Skip to content

Commit 78e27e2

Browse files
committedMar 30, 2022
async: Give predictable, reserved name to binding generated from .await expressions.
This name makes it to debuginfo and allows debuggers to identify such bindings and their captured versions in suspended async fns.
1 parent 461e807 commit 78e27e2

File tree

3 files changed

+40
-14
lines changed

3 files changed

+40
-14
lines changed
 

‎compiler/rustc_ast_lowering/src/expr.rs

+16-13
Original file line numberDiff line numberDiff line change
@@ -618,9 +618,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
618618
/// Desugar `<expr>.await` into:
619619
/// ```rust
620620
/// match ::std::future::IntoFuture::into_future(<expr>) {
621-
/// mut pinned => loop {
621+
/// mut __awaitee => loop {
622622
/// match unsafe { ::std::future::Future::poll(
623-
/// <::std::pin::Pin>::new_unchecked(&mut pinned),
623+
/// <::std::pin::Pin>::new_unchecked(&mut __awaitee),
624624
/// ::std::future::get_context(task_context),
625625
/// ) } {
626626
/// ::std::task::Poll::Ready(result) => break result,
@@ -657,21 +657,24 @@ impl<'hir> LoweringContext<'_, 'hir> {
657657
let expr = self.lower_expr_mut(expr);
658658
let expr_hir_id = expr.hir_id;
659659

660-
let pinned_ident = Ident::with_dummy_span(sym::pinned);
661-
let (pinned_pat, pinned_pat_hid) =
662-
self.pat_ident_binding_mode(span, pinned_ident, hir::BindingAnnotation::Mutable);
660+
// Note that the name of this binding must not be changed to something else because
661+
// debuggers and debugger extensions expect it to be called `__awaitee`. They use
662+
// this name to identify what is being awaited by a suspended async functions.
663+
let awaitee_ident = Ident::with_dummy_span(sym::__awaitee);
664+
let (awaitee_pat, awaitee_pat_hid) =
665+
self.pat_ident_binding_mode(span, awaitee_ident, hir::BindingAnnotation::Mutable);
663666

664667
let task_context_ident = Ident::with_dummy_span(sym::_task_context);
665668

666669
// unsafe {
667670
// ::std::future::Future::poll(
668-
// ::std::pin::Pin::new_unchecked(&mut pinned),
671+
// ::std::pin::Pin::new_unchecked(&mut __awaitee),
669672
// ::std::future::get_context(task_context),
670673
// )
671674
// }
672675
let poll_expr = {
673-
let pinned = self.expr_ident(span, pinned_ident, pinned_pat_hid);
674-
let ref_mut_pinned = self.expr_mut_addr_of(span, pinned);
676+
let awaitee = self.expr_ident(span, awaitee_ident, awaitee_pat_hid);
677+
let ref_mut_awaitee = self.expr_mut_addr_of(span, awaitee);
675678
let task_context = if let Some(task_context_hid) = self.task_context {
676679
self.expr_ident_mut(span, task_context_ident, task_context_hid)
677680
} else {
@@ -681,7 +684,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
681684
let new_unchecked = self.expr_call_lang_item_fn_mut(
682685
span,
683686
hir::LangItem::PinNewUnchecked,
684-
arena_vec![self; ref_mut_pinned],
687+
arena_vec![self; ref_mut_awaitee],
685688
Some(expr_hir_id),
686689
);
687690
let get_context = self.expr_call_lang_item_fn_mut(
@@ -782,8 +785,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
782785
span: self.lower_span(span),
783786
});
784787

785-
// mut pinned => loop { ... }
786-
let pinned_arm = self.arm(pinned_pat, loop_expr);
788+
// mut __awaitee => loop { ... }
789+
let awaitee_arm = self.arm(awaitee_pat, loop_expr);
787790

788791
// `match ::std::future::IntoFuture::into_future(<expr>) { ... }`
789792
let into_future_span = self.mark_span_with_reason(
@@ -799,11 +802,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
799802
);
800803

801804
// match <into_future_expr> {
802-
// mut pinned => loop { .. }
805+
// mut __awaitee => loop { .. }
803806
// }
804807
hir::ExprKind::Match(
805808
into_future_expr,
806-
arena_vec![self; pinned_arm],
809+
arena_vec![self; awaitee_arm],
807810
hir::MatchSource::AwaitDesugar,
808811
)
809812
}

‎compiler/rustc_span/src/symbol.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ symbols! {
272272
__D,
273273
__H,
274274
__S,
275+
__awaitee,
275276
__try_var,
276277
_d,
277278
_e,
@@ -1022,7 +1023,6 @@ symbols! {
10221023
pattern_parentheses,
10231024
phantom_data,
10241025
pin,
1025-
pinned,
10261026
platform_intrinsics,
10271027
plugin,
10281028
plugin_registrar,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// This test makes sure that the generator field capturing the awaitee in a `.await` expression
2+
// is called "__awaitee" in debuginfo. This name must not be changed since debuggers and debugger
3+
// extensions rely on the field having this name.
4+
5+
// ignore-tidy-linelength
6+
// compile-flags: -C debuginfo=2 --edition=2018
7+
8+
async fn foo() {}
9+
10+
async fn async_fn_test() {
11+
foo().await;
12+
}
13+
14+
// NONMSVC: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}",
15+
// MSVC: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "enum$<async_fn_debug_awaitee_field::async_fn_test::async_fn_env$0>",
16+
// CHECK: [[SUSPEND_STRUCT:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend0", scope: [[GEN]],
17+
// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "__awaitee", scope: [[SUSPEND_STRUCT]], {{.*}}, baseType: [[AWAITEE_TYPE:![0-9]*]],
18+
// NONMSVC: [[AWAITEE_TYPE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "GenFuture<async_fn_debug_awaitee_field::foo::{async_fn_env#0}>",
19+
// MSVC: [[AWAITEE_TYPE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "GenFuture<enum$<async_fn_debug_awaitee_field::foo::async_fn_env$0> >",
20+
21+
fn main() {
22+
let _fn = async_fn_test();
23+
}

0 commit comments

Comments
 (0)