-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Support #[track_caller]
on async fns
#104219
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
0c158f0
3db41d1
fa99cb8
509b947
b678e92
79c06fc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -86,7 +86,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> { | |
impl_trait_defs: Vec::new(), | ||
impl_trait_bounds: Vec::new(), | ||
allow_try_trait: Some([sym::try_trait_v2, sym::yeet_desugar_details][..].into()), | ||
allow_gen_future: Some([sym::gen_future][..].into()), | ||
allow_gen_future: Some([sym::gen_future, sym::closure_track_caller][..].into()), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if it makes sense to split I think it's fine like this, since |
||
allow_into_future: Some([sym::into_future][..].into()), | ||
generics_def_id_map: Default::default(), | ||
}; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
// 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); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like this is very broken, the parent here might be just a normal function, not necessarily the desugaring of an
async fn
, see #105134