Change:
<ins> // run-pass // edition:2021 // needs-unwind #![feature(closure_track_caller)] use std::future::Future; use std::panic; use std::sync::{Arc, Mutex}; use std::task::{Context, Poll, Wake}; use std::thread::{self, Thread}; /// A waker that wakes up the current thread when called. struct ThreadWaker(Thread); impl Wake for ThreadWaker { fn wake(self: Arc<Self>) { self.0.unpark(); } } /// Run a future to completion on the current thread. fn block_on<T>(fut: impl Future<Output = T>) -> T { // Pin the future so it can be polled. let mut fut = Box::pin(fut); // Create a new context to be passed to the future. let t = thread::current(); let waker = Arc::new(ThreadWaker(t)).into(); let mut cx = Context::from_waker(&waker); // Run the future to completion. loop { match fut.as_mut().poll(&mut cx) { Poll::Ready(res) => return res, Poll::Pending => thread::park(), } } } async fn bar() { panic!() } async fn foo() { bar().await } #[track_caller] async fn bar_track_caller() { panic!() } async fn foo_track_caller() { bar_track_caller().await } fn panicked_at(f: impl FnOnce() + panic::UnwindSafe) -> u32 { let loc = Arc::new(Mutex::new(None)); let hook = panic::take_hook(); { let loc = loc.clone(); panic::set_hook(Box::new(move |info| { *loc.lock().unwrap() = info.location().map(|loc| loc.line()) })); } panic::catch_unwind(f).unwrap_err(); panic::set_hook(hook); let x = loc.lock().unwrap().unwrap(); x } fn main() { assert_eq!(panicked_at(|| block_on(foo())), 41); assert_eq!(panicked_at(|| block_on(foo_track_caller())), 54); } </ins>

Discussion:
I tried: I expected the seventh line to be the panic location, but I got this: <details<summaryWith <codeRUSTBACKTRACE=1</code</summary</details%20-%3E%20!%20%7B%0A%20%20%20%20panic!()%3B%0A%7D%0A%0Afn%20main()%20%7B%0A%20%20%20%20futures%3A%3Aexecutor%3A%3Ablockon(async%20%7B%20panic().await%20%7D)%3B%0A%7D%0A) (tried using nightly 2020-11-06 ) I can achieve the result I expected by implementing a manually: Output: %5D%0A%0Ause%20std%3A%3A%7B%0A%20%20%20%20future%3A%3AFuture%2C%0A%20%20%20%20pin%3A%3APin%2C%0A%20%20%20%20task%3A%3A%7BContext%2C%20Poll%7D%2C%0A%7D%3B%0A%0Astruct%20Panic%3B%0A%0Aimpl%20Future%20for%20Panic%20%7B%0A%20%20%20%20type%20Output%20%3D%20!%3B%0A%0A%20%20%20%20%23%5Btrackcaller%5D%0A%20%20%20%20fn%20poll(self%3A%20Pin%3C%26mut%20Self%3E%2C%20%3A%20%26mut%20Context%3C%27%3E)%20-%3E%20Poll%3CSelf%3A%3AOutput%3E%20%7B%0A%20%20%20%20%20%20%20%20panic!

()%0A%20%20%20%20%7D%0A%7D%0A%0Afn%20main()%20%7B%0A%20%20%20%20futures%3A%3Aexecutor%3A%3Ablockon()%3B%0A%7D%0A) I noticed that (in the backtrace) the compiler generated a closure (?) for the , so may be related. modify labels: A-async-await A-attributes
This seems to be working correctly. The call to does not actually panic, so the does nothing. just returns a future that, when polled, will panic.
But I expect it to work further: automatically generates the I implemented manually, with on and the generated closure/. (Feature request) It's even better if could work on blocks as well.
Sorry for my wrong interpretation of this issue. But currently on s does nothing and compiles without warning, so maybe this is also a ?
Since the call to an can never panic (it always returns an ), I think forwarding the attribute to the returned closure would make sense. This would require impementing (if only on nightly), so that the desugaring can forward as needed.
Since this issue was classified as a feature request, I edited the title to make it clear.
Forwarding to the poll function does seem reasonable to me. any thoughts on this?
Forwarding to the generated future SGTM.