Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
170 changes: 170 additions & 0 deletions src/tools/miri/tests/pass/async-panic-track-caller.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
// This test is duplicated (with changes) at
// tests/ui/async-await/track-caller/panic-track-caller.rs

//@ edition:2021
//@ revisions: afn cls afn_cls nofeat
//@ run-native
//
//
//
// Padding comment so that the line numbers are the same as panic-track-caller.rs
#![feature(stmt_expr_attributes)]
#![cfg_attr(any(afn, afn_cls), feature(async_fn_track_caller))]
#![cfg_attr(any(cls, afn_cls), feature(closure_track_caller))]
#![allow(unused)]

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() {
let future = bar();
future.await;
}

#[cfg_attr(any(cls, nofeat), expect(ungated_async_fn_track_caller))]
#[track_caller]
async fn bar_track_caller() {
panic!()
}

async fn foo_track_caller() {
let future = bar_track_caller();
future.await;
}

struct Foo;

impl Foo {
#[cfg_attr(any(cls, nofeat), expect(ungated_async_fn_track_caller))]
#[track_caller]
async fn bar_assoc() {
panic!();
}
}

async fn foo_assoc() {
let future = Foo::bar_assoc();
future.await;
}

// Since compilation is expected to fail for this fn when `closure_track_caller`
// is disabled, we test that separately in `async-closure-gate.rs`
#[cfg(any(cls, afn_cls))]
async fn foo_closure() {
let closure = #[track_caller]
async || {
panic!();
};
let future = closure();
future.await;
}

// Since compilation is expected to fail for this fn when `closure_track_caller`
// is disabled, we test that separately in `async-closure-gate.rs`
#[cfg(any(cls, afn_cls))]
async fn foo_block() {
let future = #[track_caller]
async {
panic!();
};
future.await;
}

#[cfg_attr(any(cls, nofeat), expect(ungated_async_fn_track_caller))]
#[track_caller]
async fn bar_manual_poll() {
panic!();
}

fn foo_manual_poll() {
let future = bar_manual_poll();
let future = std::pin::pin!(future);
let mut cx = std::task::Context::from_waker(std::task::Waker::noop());
let res = future.poll(&mut cx);
assert_eq!(res, std::task::Poll::Ready(()));
}

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
}

// FIXME(async_fn_track_caller): Currently, #[track_caller] on an async function
// uses the location where the future is awaited or polled.
// The correct behavior as per T-lang is to use the location where the function is called.
fn main() {
assert_eq!(panicked_at(|| block_on(foo())), 51);

#[cfg(any(afn, afn_cls))]
assert_eq!(panicked_at(|| block_on(foo_track_caller())), 67);
#[cfg(any(cls, nofeat))]
assert_eq!(panicked_at(|| block_on(foo_track_caller())), 62);

#[cfg(any(afn, afn_cls))]
assert_eq!(panicked_at(|| block_on(foo_assoc())), 82);
#[cfg(any(cls, nofeat))]
assert_eq!(panicked_at(|| block_on(foo_assoc())), 76);

// FIXME(closure_track_caller): if closure_track_caller is enabled, but
// async_fn_track_caller is disabled, then #[track_caller] on async closures
// silently do nothing. Either it should function, or we should emit a warning.
// See #161961
#[cfg(cls)]
assert_eq!(panicked_at(|| block_on(foo_closure())), 91);
#[cfg(afn_cls)]
assert_eq!(panicked_at(|| block_on(foo_closure())), 94);

#[cfg(any(cls, afn_cls))]
assert_eq!(panicked_at(|| block_on(foo_block())), 105);

#[cfg(any(afn, afn_cls))]
assert_eq!(panicked_at(|| foo_manual_poll()), 118);
#[cfg(any(cls, nofeat))]
assert_eq!(panicked_at(|| foo_manual_poll()), 111);
}
12 changes: 6 additions & 6 deletions tests/ui/async-await/track-caller/async-block.afn.stderr
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
error[E0658]: `#[track_caller]` on closures is currently unstable
--> $DIR/async-block.rs:8:13
--> $DIR/async-block.rs:11:13
|
LL | let _ = #[track_caller] async {
LL | let _ = #[track_caller]
| ^^^^^^^^^^^^^^^
|
= note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
= help: add `#![feature(closure_track_caller)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date

error[E0658]: `#[track_caller]` on closures is currently unstable
--> $DIR/async-block.rs:15:13
--> $DIR/async-block.rs:19:13
|
LL | let _ = #[track_caller] async {
LL | let _ = #[track_caller]
| ^^^^^^^^^^^^^^^
|
= note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
= help: add `#![feature(closure_track_caller)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date

error[E0658]: `#[track_caller]` on closures is currently unstable
--> $DIR/async-block.rs:23:17
--> $DIR/async-block.rs:28:17
|
LL | let _ = #[track_caller] async {
LL | let _ = #[track_caller]
| ^^^^^^^^^^^^^^^
|
= note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
Expand Down
42 changes: 42 additions & 0 deletions tests/ui/async-await/track-caller/async-block.cls.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
error: `#[track_caller]` on async functions is a no-op
--> $DIR/async-block.rs:16:1
|
LL | #[track_caller]
| ^^^^^^^^^^^^^^^
LL |
LL | / async fn foo() {
LL | | let _ = #[track_caller]
LL | |
LL | | async {};
LL | | }
| |_- this function will not propagate the caller location
|
= note: see issue #110011 <https://github.com/rust-lang/rust/issues/110011> for more information
= help: add `#![feature(async_fn_track_caller)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
note: the lint level is defined here
--> $DIR/async-block.rs:6:9
|
LL | #![deny(ungated_async_fn_track_caller)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: `#[track_caller]` on async functions is a no-op
--> $DIR/async-block.rs:24:1
|
LL | #[track_caller]
| ^^^^^^^^^^^^^^^
LL |
LL | / async fn foo2() {
LL | | let _ = async {
LL | | let _ = #[track_caller]
... |
LL | | };
LL | | }
| |_- this function will not propagate the caller location
|
= note: see issue #110011 <https://github.com/rust-lang/rust/issues/110011> for more information
= help: add `#![feature(async_fn_track_caller)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date

error: aborting due to 2 previous errors

12 changes: 6 additions & 6 deletions tests/ui/async-await/track-caller/async-block.nofeat.stderr
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
error[E0658]: `#[track_caller]` on closures is currently unstable
--> $DIR/async-block.rs:8:13
--> $DIR/async-block.rs:11:13
|
LL | let _ = #[track_caller] async {
LL | let _ = #[track_caller]
| ^^^^^^^^^^^^^^^
|
= note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
= help: add `#![feature(closure_track_caller)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date

error[E0658]: `#[track_caller]` on closures is currently unstable
--> $DIR/async-block.rs:15:13
--> $DIR/async-block.rs:19:13
|
LL | let _ = #[track_caller] async {
LL | let _ = #[track_caller]
| ^^^^^^^^^^^^^^^
|
= note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
= help: add `#![feature(closure_track_caller)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date

error[E0658]: `#[track_caller]` on closures is currently unstable
--> $DIR/async-block.rs:23:17
--> $DIR/async-block.rs:28:17
|
LL | let _ = #[track_caller] async {
LL | let _ = #[track_caller]
| ^^^^^^^^^^^^^^^
|
= note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
Expand Down
27 changes: 16 additions & 11 deletions tests/ui/async-await/track-caller/async-block.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,32 @@
//@ edition:2021
//@ revisions: afn nofeat
//@ revisions: afn cls afn_cls nofeat
//@[afn_cls] check-pass

#![feature(stmt_expr_attributes)]
#![cfg_attr(afn, feature(async_fn_track_caller))]
#![deny(ungated_async_fn_track_caller)]
#![cfg_attr(any(afn, afn_cls), feature(async_fn_track_caller))]
#![cfg_attr(any(cls, afn_cls), feature(closure_track_caller))]

fn main() {
let _ = #[track_caller] async {
//~^ ERROR `#[track_caller]` on closures is currently unstable [E0658]
};
let _ = #[track_caller]
//[nofeat,afn]~^ ERROR `#[track_caller]` on closures is currently unstable [E0658]
async {};
}

#[track_caller]
//[cls]~^ ERROR `#[track_caller]` on async functions is a no-op
async fn foo() {
let _ = #[track_caller] async {
//~^ ERROR `#[track_caller]` on closures is currently unstable [E0658]
};
let _ = #[track_caller]
//[nofeat,afn]~^ ERROR `#[track_caller]` on closures is currently unstable [E0658]
async {};
}

#[track_caller]
//[cls]~^ ERROR `#[track_caller]` on async functions is a no-op
async fn foo2() {
let _ = async {
let _ = #[track_caller] async {
//~^ ERROR `#[track_caller]` on closures is currently unstable [E0658]
};
let _ = #[track_caller]
//[nofeat,afn]~^ ERROR `#[track_caller]` on closures is currently unstable [E0658]
async {};
};
}
Loading
Loading