From 3db41d13f08db377c9bc516d8f285f61ed668edd Mon Sep 17 00:00:00 2001 From: Eric Holk Date: Tue, 11 Oct 2022 16:37:54 -0700 Subject: wip: trying to enable #[track_caller] on async fn --- compiler/rustc_ast_lowering/src/expr.rs | 20 ++++++- compiler/rustc_ast_lowering/src/item.rs | 2 +- src/test/ui/async-await/panic-no-track-caller.rs | 74 ----------------------- src/test/ui/async-await/panic-track-caller.rs | 75 ++++++++++++++++++++++++ 4 files changed, 95 insertions(+), 76 deletions(-) delete mode 100644 src/test/ui/async-await/panic-no-track-caller.rs create mode 100644 src/test/ui/async-await/panic-track-caller.rs diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 46886c518af..61d91874e61 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -617,8 +617,26 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ExprKind::Closure(c) }; + let generator_hir_id = self.lower_node_id(closure_node_id); + // FIXME: only add track caller if the parent is track_caller + self.lower_attrs( + generator_hir_id, + &[Attribute { + kind: AttrKind::Normal(ptr::P(NormalAttr { + item: AttrItem { + path: Path::from_ident(Ident::new(sym::track_caller, span)), + args: MacArgs::Empty, + tokens: None, + }, + tokens: None, + })), + id: self.tcx.sess.parse_sess.attr_id_generator.mk_attr_id(), + style: AttrStyle::Outer, + span, + }], + ); let generator = hir::Expr { - hir_id: self.lower_node_id(closure_node_id), + hir_id: generator_hir_id, kind: generator_kind, span: self.lower_span(span), }; diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 9a46444d823..e9cc53b7138 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -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()), allow_into_future: Some([sym::into_future][..].into()), generics_def_id_map: Default::default(), }; diff --git a/src/test/ui/async-await/panic-no-track-caller.rs b/src/test/ui/async-await/panic-no-track-caller.rs deleted file mode 100644 index 934764912d3..00000000000 --- a/src/test/ui/async-await/panic-no-track-caller.rs +++ /dev/null @@ -1,74 +0,0 @@ -// run-pass -// edition:2021 - -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.0.unpark(); - } -} - -/// Run a future to completion on the current thread. -fn block_on(fut: impl Future) -> 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())), 39); - assert_eq!(panicked_at(|| block_on(foo_track_caller())), 52); -} diff --git a/src/test/ui/async-await/panic-track-caller.rs b/src/test/ui/async-await/panic-track-caller.rs new file mode 100644 index 00000000000..76776d41c57 --- /dev/null +++ b/src/test/ui/async-await/panic-track-caller.rs @@ -0,0 +1,75 @@ +// run-pass +// edition:2021 +#![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.0.unpark(); + } +} + +/// Run a future to completion on the current thread. +fn block_on(fut: impl Future) -> 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())), 39); + assert_eq!(panicked_at(|| block_on(foo_track_caller())), 52); +} -- cgit 1.4.1-3-g733a5