Skip to content

Make #[track_caller] async fn track the caller, not the poller/awaiter - #163396

Open
theemathas wants to merge 9 commits into
rust-lang:mainfrom
theemathas:async-track-caller-not-poller
Open

theemathas wants to merge 9 commits into
rust-lang:mainfrom
theemathas:async-track-caller-not-poller

Conversation

@theemathas

@theemathas theemathas commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

View all comments

An LLM was used to locate relevant code, suggest ideas, and review the code. However, I manually wrote all code, and I take all responsibility for all code written and all decisions made.

Tracking issue (async_fn_track_caller): #110011

Related tracking issue (closure_track_caller): #87417

This PR is stacked on top of #163262 (first commit in this PR) and #163746 (the second commit in this PR, which was cherry-picked in). The third commit adds extensive tests for behavior touched in this PR. Commits 4-9 are the actual implementation, and also modification of the tests to reflect this new behavior.

This PR makes coroutines desugared from #[track_caller] async fn track the caller of the function, not the poller/awaiter of the coroutine. This is done as per T-lang's decision at #110011 (comment). The implementation modifies AST lowering to add an upvar to the coroutine, which stores the relevant caller location.

In both codegen and in consteval/miri, we read the relevant upvar from the coroutine at the point in time where we need access to the &Location reference (either when we call the caller_location intrinsic, when we panic, or when we call another #[track_caller] function). We only dereference this reference as needed, when we actually need the Location information.

This PR changes the behavior of async fn, but not of async closures, due to difficulties I've noted at #t-compiler/help > Help with `async_fn_track_caller` @ 💬

This PR's implementation assumes that the desired behavior in #110011 (comment) is the behavior that I think makes the most sense.

This PR corrects the behavior of #163406 when the async_fn_track_caller feature is enabled, but does not give a warning when the feature is disabled (resulting in the pre-existing broken behavior).

The tests pass on cranelift when I run ./x test ui --test-codegen-backend cranelift -- async-await/track-caller/panic-track-caller-no-unwind.rs. (Cranelift doesn't support unwinding.)

r? compiler

@rustbot rustbot added A-attributes Area: Attributes (`#[…]`, `#![…]`) S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Sep 27, 2026
@theemathas
theemathas force-pushed the async-track-caller-not-poller branch 3 times, most recently from f21a754 to 7e01c99 Compare September 28, 2026 15:47
@rust-log-analyzer

This comment has been minimized.

@rust-bors

This comment has been minimized.

@theemathas
theemathas force-pushed the async-track-caller-not-poller branch from 7e01c99 to c87bff0 Compare September 29, 2026 11:52
Comment on lines +988 to +997
if is_in_trait_impl {
// Check if we need to "inherit" #[track_caller] from the trait definition.
let Some(trait_item_def_id) =
self.get_partial_res(node_id).and_then(|r| r.expect_full_res().opt_def_id())
else {
self.dcx().span_delayed_bug(span, "could not resolve trait item being implemented");
return false;
};
return find_attr!(self.tcx, trait_item_def_id, TrackCaller(_));
}

@theemathas theemathas Sep 29, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand what this is doing, but I'm doing the same thing as this existing code:

let (effective_ident, impl_kind) = if is_in_trait_impl {
let trait_item_def_id = self
.get_partial_res(i.id)
.and_then(|r| r.expect_full_res().opt_def_id())
.ok_or_else(|| {
self.dcx()
.span_delayed_bug(span, "could not resolve trait item being implemented")
});

View changes since the review

Comment thread compiler/rustc_mir_transform/src/check_inline.rs
Comment on lines +108 to 110
///
/// FIXME(async_fn_track_caller): What if the Location is stored inside a coroutine upvar?
fn resolve_tracked_call_location(body: &Body, inherited: Option<MirConst>) -> MirConst {

@theemathas theemathas Sep 29, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this, and do I need to modify it?

View changes since the review

@theemathas
theemathas marked this pull request as ready for review September 29, 2026 12:19
@rustbot

rustbot commented Sep 29, 2026

Copy link
Copy Markdown
Collaborator

miri is developed in its own repository. If the Miri part of this change can be broken out, consider making this change to rust-lang/miri instead. However, if Miri needs adjusting for rustc changes, just ignore this message.

cc @rust-lang/miri

Some changes occurred to the CTFE machinery

cc @RalfJung, @oli-obk, @lcnr

Some changes occurred in compiler/rustc_attr_ir

cc @jdonszelmann, @JonathanBrouwer

Some changes occurred to MIR optimizations

cc @rust-lang/wg-mir-opt

Some changes occurred to the intrinsics. Make sure the CTFE / Miri interpreter
gets adapted for the changes, if necessary.

cc @rust-lang/miri, @RalfJung, @oli-obk, @lcnr

Some changes occurred to the CTFE / Miri interpreter

cc @rust-lang/miri

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Sep 29, 2026
Comment thread compiler/rustc_const_eval/src/interpret/eval_context.rs Outdated
Comment thread compiler/rustc_const_eval/src/interpret/operand.rs Outdated
@theemathas
theemathas force-pushed the async-track-caller-not-poller branch from c87bff0 to b14e6ed Compare September 29, 2026 13:07
Comment thread compiler/rustc_const_eval/src/interpret/intrinsics.rs Outdated
@theemathas

This comment was marked as resolved.

Comment thread compiler/rustc_codegen_ssa/src/mir/block.rs
@theemathas
theemathas force-pushed the async-track-caller-not-poller branch from b14e6ed to e1d818f Compare October 1, 2026 13:57
@rustbot

This comment has been minimized.

@theemathas
theemathas force-pushed the async-track-caller-not-poller branch from e1d818f to 6fcdc09 Compare October 1, 2026 14:56
@theemathas

Copy link
Copy Markdown
Contributor Author

I split up the implementation into multiple commits, hopefully making reviewing easier. (And also hopefully making it less confusing for me.)

@theemathas
theemathas force-pushed the async-track-caller-not-poller branch 2 times, most recently from 6fcdc09 to 473dbf0 Compare October 1, 2026 15:01
@theemathas theemathas changed the title Make #[track_caller] async fn track the caller, not the poller Make #[track_caller] async fn track the caller, not the poller/awaiter Oct 2, 2026
@theemathas
theemathas force-pushed the async-track-caller-not-poller branch from 473dbf0 to 57abba7 Compare October 2, 2026 11:02
@theemathas

Copy link
Copy Markdown
Contributor Author

I've reimplemented this PR in the Miri portion so that it doesn't walk the stack, but instead passes the caller location argument down the stack, as per @RalfJung's suggestion.

@theemathas theemathas added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Oct 7, 2026
@rust-log-analyzer

This comment has been minimized.

@theemathas
theemathas force-pushed the async-track-caller-not-poller branch from 2f38293 to 4598eb9 Compare October 7, 2026 15:48
@rustbot

rustbot commented Oct 7, 2026

Copy link
Copy Markdown
Collaborator

rustc_codegen_cranelift is developed in its own repository. If possible, consider making this change to rust-lang/rustc_codegen_cranelift instead.

cc @bjorn3

@rust-log-analyzer

This comment has been minimized.

@theemathas
theemathas force-pushed the async-track-caller-not-poller branch from 4598eb9 to 9c81c0d Compare October 7, 2026 16:01
@theemathas

This comment was marked as resolved.

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Oct 7, 2026
@rustbot

This comment was marked as resolved.

@theemathas

This comment was marked as resolved.

rust-bors Bot pushed a commit that referenced this pull request Oct 8, 2026
…try>

Make `#[track_caller] async fn` track the caller, not the poller/awaiter


try-job: dist-x86_64-linux
@rust-bors

This comment was marked as resolved.

@theemathas

This comment was marked as resolved.

@rust-bors

This comment was marked as resolved.

@theemathas

theemathas commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor Author

Added tests that are verified locally to pass for cranelift.

@rustbot ready

Edit: Maybe it might be better if I use #[cfg(panic = "unwind")] instead? (Edit: Done.)

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Oct 8, 2026
@theemathas
theemathas force-pushed the async-track-caller-not-poller branch from 822ca16 to aa2bf51 Compare October 9, 2026 12:00
@theemathas
theemathas force-pushed the async-track-caller-not-poller branch from aa2bf51 to f857e66 Compare October 9, 2026 13:13
@theemathas

Copy link
Copy Markdown
Contributor Author

Tested locally for cranelift by applying the following change and running ./x test ui --test-codegen-backend cranelift -- async-await/track-caller/panic-track-caller.rs

diff --git a/tests/ui/async-await/track-caller/panic-track-caller.rs b/tests/ui/async-await/track-caller/panic-track-caller.rs
index 99dec25fdca..248db622bf6 100644
--- a/tests/ui/async-await/track-caller/panic-track-caller.rs
+++ b/tests/ui/async-await/track-caller/panic-track-caller.rs
@@ -1,15 +1,15 @@
 // This test is duplicated (with changes) at
 // src/tools/miri/tests/pass/async-panic-track-caller.rs
-
+//@ no-prefer-dynamic
 //@ run-pass
 //@ edition:2024
 //@ revisions: nofeat afn cls afn_cls nofeat_opt afn_opt cls_opt afn_cls_opt
-//@[nofeat_opt] compile-flags: -O -Zinline-mir-hint-threshold=1000
-//@[afn_opt] compile-flags: -O -Zinline-mir-hint-threshold=1000
-//@[cls_opt] compile-flags: -O -Zinline-mir-hint-threshold=1000
-//@[afn_cls_opt] compile-flags: -O -Zinline-mir-hint-threshold=1000
+//@[nofeat_opt] compile-flags: -O -Zinline-mir-hint-threshold=1000 -Cpanic=abort
+//@[afn_opt] compile-flags: -O -Zinline-mir-hint-threshold=1000 -Cpanic=abort
+//@[cls_opt] compile-flags: -O -Zinline-mir-hint-threshold=1000 -Cpanic=abort
+//@[afn_cls_opt] compile-flags: -O -Zinline-mir-hint-threshold=1000 -Cpanic=abort
+//@ compile-flags: -Cpanic=abort
 // gate-test-async_fn_track_caller
-//
 #![feature(stmt_expr_attributes, coroutines, coroutine_trait, gen_blocks)]
 #![cfg_attr(any(afn, afn_cls, afn_opt, afn_cls_opt), feature(async_fn_track_caller))]
 #![cfg_attr(any(cls, afn_cls, cls_opt, afn_cls_opt), feature(closure_track_caller))]

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-attributes Area: Attributes (`#[…]`, `#![…]`) S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants