macro_rules! ext_trait { ($name:ident: $sealed:ident for $t:ty {$( $(#[$method_meta:meta])* fn $method:ident -> $impl:ident; )+}) => { trait $sealed {} #[allow(private_bounds)] pub trait $name: $sealed {$( $(#[$method_meta])* fn $method(self) -> $crate::DropGuard<$impl>; )+} impl $sealed for $t {} impl $name for $t {$( fn $method(self) -> $crate::DropGuard<$impl> { $crate::DropGuard::with_data($impl, self) } )+} }; } pub(crate) use ext_trait; macro_rules! join_handle_ext { ($name:ident for $t:ident, $impl:ident, $call_method:ident, |$result_bind:ident| $result:ty) => { use std::marker::PhantomData; use crate::DropGuard; pub struct $impl(PhantomData T>); impl DropFn for $impl { type Data = $t; fn on_drop(self, data: Self::Data) { _ = data.$call_method(); } } trait Sealed {} pub trait $name { type Result; #[doc = concat!("Wraps the join handle in a [`DropGuard`] that will call [`", stringify!($t), "::", stringify!($call_method), "`] on drop.")] fn abort_on_drop(self) -> DropGuard<$impl>; } impl Sealed for $t {} impl $name for $t { type Result = T; fn abort_on_drop(self) -> DropGuard<$impl> { DropGuard::with_data($impl(PhantomData), self) } } impl<$result_bind> core::future::Future for DropGuard<$impl<$result_bind>> { type Output = $result; fn poll( mut self: core::pin::Pin<&mut Self>, cx: &mut core::task::Context<'_>, ) -> core::task::Poll { core::pin::Pin::new(&mut **self).poll(cx) } } }; } pub(crate) use join_handle_ext;