maybe_unwind/
futures.rs

1use crate::unwind::{maybe_unwind, Unwind};
2use futures_core::{
3    future::Future,
4    task::{self, Poll},
5};
6use std::{
7    panic::{AssertUnwindSafe, UnwindSafe},
8    pin::Pin,
9};
10
11/// A future for the [`maybe_unwind`] method.
12///
13/// [`maybe_unwind`]: ./trait.FutureMaybeUnwindExt.html#method.maybe_unwind
14#[derive(Debug)]
15#[cfg_attr(docs, doc(cfg(feature = "futures")))]
16#[must_use = "futures do nothing unless you `.await` or poll them"]
17pub struct MaybeUnwind<F> {
18    inner: F,
19}
20
21impl<F> Future for MaybeUnwind<F>
22where
23    F: Future + UnwindSafe,
24{
25    type Output = Result<F::Output, Unwind>;
26
27    fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
28        let inner = unsafe { self.map_unchecked_mut(|me| &mut me.inner) };
29        maybe_unwind(AssertUnwindSafe(|| inner.poll(cx)))?.map(Ok)
30    }
31}
32
33/// An extension trait for `Future`s that provides an adaptor for capturing
34/// the unwinding panic information.
35#[cfg_attr(docs, doc(cfg(feature = "futures")))]
36pub trait FutureMaybeUnwindExt: Future + Sized {
37    /// Catches unwinding panics while polling the future.
38    ///
39    /// This is a variant of [`catch_unwind`] that also captures
40    /// the panic information.
41    ///
42    /// # Example
43    ///
44    /// ```
45    /// use maybe_unwind::FutureMaybeUnwindExt as _;
46    ///
47    /// std::panic::set_hook(Box::new(|info| {
48    ///     maybe_unwind::capture_panic_info(info);
49    /// }));
50    ///
51    /// # futures_executor::block_on(async {
52    /// let res = do_something_async().maybe_unwind().await;
53    /// # drop(res);
54    /// # });
55    /// # async fn do_something_async() {}
56    /// ```
57    ///
58    /// [`catch_unwind`]: https://docs.rs/futures/0.3/futures/future/trait.FutureExt.html#method.catch_unwind
59    fn maybe_unwind(self) -> MaybeUnwind<Self>
60    where
61        Self: UnwindSafe,
62    {
63        MaybeUnwind { inner: self }
64    }
65}
66
67impl<F: Future> FutureMaybeUnwindExt for F {}