diff --git a/compiler/rustc_error_messages/locales/en-US/lint.ftl b/compiler/rustc_error_messages/locales/en-US/lint.ftl index 3980f9a2a7a5..a36a511bd4aa 100644 --- a/compiler/rustc_error_messages/locales/en-US/lint.ftl +++ b/compiler/rustc_error_messages/locales/en-US/lint.ftl @@ -350,7 +350,8 @@ lint_builtin_mutable_transmutes = lint_builtin_unstable_features = unstable feature -lint_ungated_async_fn_track_caller = `#[track_caller]` on async functions is a no-op, unless the `closure_track_caller` feature is enabled +lint_ungated_async_fn_track_caller = `#[track_caller]` on async functions is a no-op + .suggestion = enable this feature lint_builtin_unreachable_pub = unreachable `pub` {$what} .suggestion = consider restricting its visibility diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index d7d91a12e658..e90572cb2388 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1404,10 +1404,16 @@ impl<'tcx> LateLintPass<'tcx> for UngatedAsyncFnTrackCaller { if let Some(attr) = maybe_track_caller { cx.struct_span_lint( UNGATED_ASYNC_FN_TRACK_CALLER, - span.with_hi(attr.span.hi()), + attr.span, fluent::lint_ungated_async_fn_track_caller, - |lint| lint, - ); + |lint| { + lint.span_label(span, "this function will not propagate the caller location"); + if cx.tcx.sess.is_nightly_build() { + lint.span_suggestion(attr.span, fluent::suggestion, "#[closure_track_caller]", Applicability::MachineApplicable); + } + lint + } + ); } } } diff --git a/src/test/ui/async-await/track-caller/issue-104588-no-op-panic-track-caller.rs b/src/test/ui/async-await/track-caller/issue-104588-no-op-panic-track-caller.rs deleted file mode 100644 index 5ef40408e269..000000000000 --- a/src/test/ui/async-await/track-caller/issue-104588-no-op-panic-track-caller.rs +++ /dev/null @@ -1,78 +0,0 @@ -// run-pass -// edition:2021 -// needs-unwind - - -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] //~ WARN `#[track_caller]` on async functions is a no-op, unless the `closure_track_caller` feature is enabled [ungated_async_fn_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); - // Since the `closure_track_caller` feature is not enabled, the - // `track_caller annotation does nothing. - assert_eq!(panicked_at(|| block_on(foo_track_caller())), 50); -} diff --git a/src/test/ui/async-await/track-caller/issue-104588-no-op-panic-track-caller.stderr b/src/test/ui/async-await/track-caller/issue-104588-no-op-panic-track-caller.stderr deleted file mode 100644 index 5bfd9ed8490f..000000000000 --- a/src/test/ui/async-await/track-caller/issue-104588-no-op-panic-track-caller.stderr +++ /dev/null @@ -1,12 +0,0 @@ -warning: `#[track_caller]` on async functions is a no-op, unless the `closure_track_caller` feature is enabled - --> $DIR/issue-104588-no-op-panic-track-caller.rs:48:16 - | -LL | #[track_caller] - | ________________^ -LL | | async fn bar_track_caller() { - | |_ - | - = note: `#[warn(ungated_async_fn_track_caller)]` on by default - -warning: 1 warning emitted - diff --git a/src/test/ui/async-await/track-caller/issue-104588-no-op-track-caller.rs b/src/test/ui/async-await/track-caller/issue-104588-no-op-track-caller.rs index 146d3c9ec53d..6443e14296da 100644 --- a/src/test/ui/async-await/track-caller/issue-104588-no-op-track-caller.rs +++ b/src/test/ui/async-await/track-caller/issue-104588-no-op-track-caller.rs @@ -1,7 +1,7 @@ // check-pass // edition:2021 -#[track_caller] //~ WARN `#[track_caller]` on async functions is a no-op, unless the `closure_track_caller` feature is enabled +#[track_caller] //~ WARN `#[track_caller]` on async functions is a no-op async fn foo() {} fn main() { diff --git a/src/test/ui/async-await/track-caller/issue-104588-no-op-track-caller.stderr b/src/test/ui/async-await/track-caller/issue-104588-no-op-track-caller.stderr index bf66cc9ea90f..bd39c9d092ca 100644 --- a/src/test/ui/async-await/track-caller/issue-104588-no-op-track-caller.stderr +++ b/src/test/ui/async-await/track-caller/issue-104588-no-op-track-caller.stderr @@ -1,10 +1,10 @@ -warning: `#[track_caller]` on async functions is a no-op, unless the `closure_track_caller` feature is enabled - --> $DIR/issue-104588-no-op-track-caller.rs:4:16 +warning: `#[track_caller]` on async functions is a no-op + --> $DIR/issue-104588-no-op-track-caller.rs:4:1 | -LL | #[track_caller] - | ________________^ -LL | | async fn foo() {} - | |_ +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ help: enable this feature: `#[closure_track_caller]` +LL | async fn foo() {} + | ----------------- this function will not propagate the caller location | = note: `#[warn(ungated_async_fn_track_caller)]` on by default diff --git a/src/test/ui/async-await/track-caller/panic-track-caller.nofeat.stderr b/src/test/ui/async-await/track-caller/panic-track-caller.nofeat.stderr new file mode 100644 index 000000000000..e0201f2238dd --- /dev/null +++ b/src/test/ui/async-await/track-caller/panic-track-caller.nofeat.stderr @@ -0,0 +1,14 @@ +warning: `#[track_caller]` on async functions is a no-op + --> $DIR/panic-track-caller.rs:50:1 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ help: enable this feature: `#[closure_track_caller]` +LL | / async fn bar_track_caller() { +LL | | panic!() +LL | | } + | |_- this function will not propagate the caller location + | + = note: `#[warn(ungated_async_fn_track_caller)]` on by default + +warning: 1 warning emitted + diff --git a/src/test/ui/async-await/track-caller/panic-track-caller.rs b/src/test/ui/async-await/track-caller/panic-track-caller.rs index 066cf97628fa..ee37e64be4fa 100644 --- a/src/test/ui/async-await/track-caller/panic-track-caller.rs +++ b/src/test/ui/async-await/track-caller/panic-track-caller.rs @@ -1,7 +1,9 @@ // run-pass // edition:2021 +// revisions: feat nofeat // needs-unwind -#![feature(closure_track_caller, async_closure, stmt_expr_attributes)] +#![feature(async_closure, stmt_expr_attributes)] +#![cfg_attr(feat, feature(closure_track_caller))] use std::future::Future; use std::panic; @@ -45,7 +47,7 @@ async fn foo() { bar().await } -#[track_caller] +#[track_caller] //[nofeat]~ WARN `#[track_caller]` on async functions is a no-op async fn bar_track_caller() { panic!() } @@ -91,8 +93,20 @@ fn panicked_at(f: impl FnOnce() + panic::UnwindSafe) -> u32 { } fn main() { - assert_eq!(panicked_at(|| block_on(foo())), 41); - assert_eq!(panicked_at(|| block_on(foo_track_caller())), 54); - assert_eq!(panicked_at(|| block_on(foo_assoc())), 67); + assert_eq!(panicked_at(|| block_on(foo())), 43); + + #[cfg(feat)] + assert_eq!(panicked_at(|| block_on(foo_track_caller())), 56); + #[cfg(nofeat)] + assert_eq!(panicked_at(|| block_on(foo_track_caller())), 52); + + #[cfg(feat)] + assert_eq!(panicked_at(|| block_on(foo_assoc())), 69); + #[cfg(nofeat)] + assert_eq!(panicked_at(|| block_on(foo_assoc())), 64); + + #[cfg(feat)] + assert_eq!(panicked_at(|| block_on(foo_closure())), 76); + #[cfg(feat)] assert_eq!(panicked_at(|| block_on(foo_closure())), 74); }