1#![doc = include_str!("../readme-parts/main.md")]
21#![no_std]
22#![forbid(non_ascii_idents)]
24#![deny(
25 future_incompatible,
26 keyword_idents,
27 elided_lifetimes_in_paths,
28 meta_variable_misuse,
29 noop_method_call,
30 pointer_structural_match,
31 unused_lifetimes,
32 unused_qualifications,
33 unsafe_op_in_unsafe_fn,
34 clippy::undocumented_unsafe_blocks,
35 clippy::wildcard_dependencies,
36 clippy::debug_assert_with_mut_call,
37 clippy::empty_line_after_outer_attr,
38 clippy::panic,
39 clippy::unwrap_used,
40 clippy::expect_used,
41 clippy::redundant_field_names,
42 clippy::rest_pat_in_fully_bound_structs,
43 clippy::unneeded_field_pattern,
44 clippy::useless_let_if_seq,
45 clippy::default_union_representation
46)]
47#![warn(clippy::pedantic)]
48#![allow(
50 clippy::inline_always,
52 clippy::must_use_candidate,
54)]
55
56use core::{
57 future::Future,
58 marker::PhantomPinned,
59 mem::{ManuallyDrop, MaybeUninit},
60 pin::Pin,
61 task::{Context, Poll},
62};
63
64pub use name_it_macros::name_it;
67
68#[rustfmt::skip]
70#[doc(hidden)]
71pub mod markers;
72
73#[doc(hidden)]
75pub unsafe trait FutParams {
76 type Fut: Future<Output = Self::Output>;
77 type Output;
78}
79
80#[doc(hidden)]
81pub use elain as _elain;
82
83#[doc(hidden)]
84#[allow(clippy::panic)]
86pub fn any<T>(_: &str) -> T {
87 panic!()
88}
89
90#[doc(hidden)]
91#[macro_export]
92macro_rules! _produce_any {
93 ($f:ident $($xs:pat),*$(,)?) => {
94 $f(
95 $($crate::any(stringify!($xs))),*
96 )
97 }
98}
99
100#[doc(hidden)]
101#[macro_export]
102macro_rules! _name_it_inner {
103 ($v:vis type $name:ident = $func:ident($($underscores:tt)*) -> $ret:ty$(;)?) => {
104 #[repr(C)]
105 $v struct $name<'fut>
106 where
107 $crate::_elain::Align<{$crate::align_of_fut(&($func as fn($($underscores)*) -> _))}>: $crate::_elain::Alignment,
108 {
109 bytes: [::core::mem::MaybeUninit<u8>; $crate::size_of_fut(&($func as fn($($underscores)*) -> _))],
110 _alignment: $crate::_elain::Align<{$crate::align_of_fut(&($func as fn($($underscores)*) -> _))}>,
111 _lifetime: ::core::marker::PhantomData<&'fut mut &'fut mut ()>,
113 _markers: $crate::markers!($crate::_produce_any!($func $($underscores)*)),
114 }
115
116 impl<'fut> $name<'fut> {
117 #[doc(hidden)]
118 $v unsafe fn new(bytes: [::core::mem::MaybeUninit<u8>; $crate::size_of_fut(&($func as fn($($underscores)*) -> _))]) -> Self {
119 Self {
120 bytes,
121 _alignment: $crate::_elain::Align::NEW,
122 _lifetime: ::core::marker::PhantomData,
123 _markers: $crate::markers::Markers::new(),
124 }
125 }
126 }
127
128 impl<'fut> ::core::future::Future for $name<'fut> {
129 type Output = $ret;
130
131 fn poll(self: ::core::pin::Pin<&mut Self>, cx: &mut ::core::task::Context<'_>) -> ::core::task::Poll<$ret> {
132 unsafe {
136 $crate::poll(
137 ::core::mem::transmute::<
138 _, ::core::pin::Pin<&mut [::core::mem::MaybeUninit<u8>; $crate::size_of_fut(&($func as fn($($underscores)*) -> _))]>
139 >(self),
140 cx, $func as fn($($underscores)*) -> _
141 )
142 }
143 }
144 }
145
146 impl<'fut> ::core::ops::Drop for $name<'fut> {
147 fn drop(&mut self) {
148 unsafe {
150 $crate::dispose(&mut self.bytes, ($func as fn($($underscores)*) -> _));
151 }
152 }
153 }
154 };
155}
156
157#[repr(transparent)]
164pub struct Named<T> {
165 #[allow(dead_code)]
167 inner: T,
168 _pinned: PhantomPinned,
169}
170
171impl<T> Named<T> {
172 #[doc(hidden)]
173 pub fn new(inner: T) -> Self {
174 Self {
175 inner,
176 _pinned: PhantomPinned,
177 }
178 }
179}
180
181impl<T> Future for Named<T>
182where
183 T: Future,
184{
185 type Output = T::Output;
186
187 #[inline]
188 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
189 unsafe { core::mem::transmute::<_, Pin<&mut T>>(self) }.poll(cx)
191 }
192}
193
194#[repr(C)]
195union Transmute<From, To> {
196 from: ManuallyDrop<From>,
197 to: ManuallyDrop<To>,
198}
199
200#[inline]
201#[doc(hidden)]
202pub unsafe fn transmute_generic<From, To>(val: From) -> To {
203 ManuallyDrop::into_inner(
204 unsafe {
206 Transmute::<From, To> {
207 from: ManuallyDrop::new(val),
208 }
209 .to
210 },
211 )
212}
213
214#[inline]
215#[doc(hidden)]
216pub unsafe fn poll<F: FutParams, const N: usize>(
217 this: Pin<&mut [MaybeUninit<u8>; N]>,
218 cx: &mut Context<'_>,
219 _: F,
220) -> Poll<F::Output> {
221 let fut = unsafe { transmute_generic::<Pin<&mut _>, Pin<&mut F::Fut>>(this) };
224 fut.poll(cx)
225}
226
227#[inline]
228#[doc(hidden)]
229pub unsafe fn dispose<F: FutParams, const N: usize>(this: &mut [MaybeUninit<u8>; N], _: F) {
230 let fut = unsafe { transmute_generic::<&mut _, &mut MaybeUninit<F::Fut>>(this) };
232 unsafe { fut.assume_init_drop() };
235}
236
237#[doc(hidden)]
238pub const fn size_of_fut<F: FutParams>(_: &F) -> usize {
239 core::mem::size_of::<F::Fut>()
240}
241
242#[doc(hidden)]
243pub const fn align_of_fut<F: FutParams>(_: &F) -> usize {
244 core::mem::align_of::<F::Fut>()
245}
246
247macro_rules! impl_fut_params {
248 ($($t:ident $($ts:ident)*)?) => {
249 unsafe impl<$($t, $($ts,)*)? R, Fut> FutParams for fn($($t, $($ts,)*)?) -> Fut
251 where
252 Fut: Future<Output = R>
253 {
254 type Fut = Fut;
255 type Output = R;
256 }
257
258 $(impl_fut_params!($($ts)*);)?
259 };
260}
261
262impl_fut_params!(
263 T00 T01 T02 T03 T04 T05 T06 T07 T08 T09 T10 T11 T12 T13 T14 T15
264 T16 T17 T18 T19 T20 T21 T22 T23 T24 T25 T26 T27 T28 T29 T30 T31
265);