1use std::{future::Future, task::Poll};
2
3pin_project_lite::pin_project! {
4 pub struct MustDoneFuture<F> {
5 #[pin]
6 inner: F,
7 guard: Option<Guard>,
8 }
9}
10
11pub trait MustDone {
12 fn must_done(self) -> MustDoneFuture<Self>
13 where
14 Self: Sized;
15}
16
17impl<F: Future> Future for MustDoneFuture<F> {
18 type Output = F::Output;
19
20 #[inline]
21 fn poll(self: std::pin::Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {
22 let this = self.project();
23 match this.inner.poll(cx) {
24 Poll::Ready(r) => {
25 std::mem::forget(this.guard.take());
26 Poll::Ready(r)
27 }
28 Poll::Pending => Poll::Pending,
29 }
30 }
31}
32
33impl<F> MustDoneFuture<F> {
34 #[inline]
35 pub fn new(inner: F) -> Self {
36 Self {
37 inner,
38 guard: Some(Guard),
39 }
40 }
41}
42
43impl<F> From<F> for MustDoneFuture<F> {
44 #[inline]
45 fn from(value: F) -> Self {
46 Self::new(value)
47 }
48}
49
50impl<T: Future + Sized> MustDone for T {
51 #[inline]
52 fn must_done(self) -> MustDoneFuture<Self>
53 where
54 Self: Sized,
55 {
56 MustDoneFuture::new(self)
57 }
58}
59
60struct Guard;
61
62impl Drop for Guard {
63 fn drop(&mut self) {
64 extern "C" {
65 #[link_name = "oops"]
66 fn trigger() -> !;
67 }
68
69 unsafe { trigger() };
70 }
71}