Skip to content

Commit 9d22cc2

Browse files
authored
Rollup merge of rust-lang#95011 - michaelwoerister:awaitee_field, r=tmandry
async: Give predictable 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. This will be useful for async stack traces, as discussed in https://internals.rust-lang.org/t/async-debugging-logical-stack-traces-setting-goals-collecting-examples/15547. I don't know if this needs some discussion by ``@rust-lang/compiler,`` e.g. about the name of the binding (`__awaitee`) or about the fact that this PR introduces a (soft) guarantee about a compiler generated name. Although, regarding the later, I think the same reasoning applies here as it does for debuginfo in general. r? ``@tmandry``
2 parents 557a22c + 78e27e2 commit 9d22cc2

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,
@@ -1019,7 +1020,6 @@ symbols! {
10191020
pattern_parentheses,
10201021
phantom_data,
10211022
pin,
1022-
pinned,
10231023
platform_intrinsics,
10241024
plugin,
10251025
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)