diff --git a/library/std/src/sync/once.rs b/library/std/src/sync/once.rs
index f76d0759561ac..511de863dc51b 100644
--- a/library/std/src/sync/once.rs
+++ b/library/std/src/sync/once.rs
@@ -256,6 +256,7 @@ impl Once {
     ///
     /// [poison]: struct.Mutex.html#poisoning
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[track_caller]
     pub fn call_once<F>(&self, f: F)
     where
         F: FnOnce(),
@@ -390,6 +391,7 @@ impl Once {
     // currently no way to take an `FnOnce` and call it via virtual dispatch
     // without some allocation overhead.
     #[cold]
+    #[track_caller]
     fn call_inner(&self, ignore_poisoning: bool, init: &mut dyn FnMut(&OnceState)) {
         let mut state_and_queue = self.state_and_queue.load(Ordering::Acquire);
         loop {
diff --git a/src/test/ui/issues/issue-87707.rs b/src/test/ui/issues/issue-87707.rs
new file mode 100644
index 0000000000000..d2e9343f86cd5
--- /dev/null
+++ b/src/test/ui/issues/issue-87707.rs
@@ -0,0 +1,15 @@
+// test for #87707
+// edition:2018
+// run-fail
+// check-run-results
+
+use std::sync::Once;
+use std::panic;
+
+fn main() {
+    let o = Once::new();
+    let _ = panic::catch_unwind(|| {
+        o.call_once(|| panic!("Here Once instance is poisoned."));
+    });
+    o.call_once(|| {});
+}
diff --git a/src/test/ui/issues/issue-87707.run.stderr b/src/test/ui/issues/issue-87707.run.stderr
new file mode 100644
index 0000000000000..8f82ccc0c2abe
--- /dev/null
+++ b/src/test/ui/issues/issue-87707.run.stderr
@@ -0,0 +1,3 @@
+thread 'main' panicked at 'Here Once instance is poisoned.', $DIR/issue-87707.rs:12:24
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+thread 'main' panicked at 'Once instance has previously been poisoned', $DIR/issue-87707.rs:14:7