scope_lock/pointer_like/
erased_static.rs

1//! `'static` versions of the most popular functions.
2//!
3//! This module contains a way to type erase popular functions for any requested type without using
4//! dynamic dispatch. It overcomes limitaions of generic free functions' instances inheriting
5//! lifetime from a generic arguments.
6//!
7use core::{
8    future::Future,
9    panic::{RefUnwindSafe, UnwindSafe},
10    pin::Pin,
11    task,
12};
13
14use super::{PointerDeref, PointerDerefMut, PointerIntoInner, PointerLike, PointerPinUnforgotten};
15
16/// Get `'static` function of drop on a `P` pointer type.
17///
18/// # Safety
19///
20/// Only valid pointers of the same original smart-pointer type `P` must be passed to the returned
21/// closure otherwise causing undefined behaviour.
22pub const unsafe fn fn_drop<P: PointerLike>(
23) -> impl Fn(*mut ()) + Copy + Send + Sync + UnwindSafe + RefUnwindSafe + Unpin + 'static {
24    |erased_ptr| drop(unsafe { P::from_ptr(erased_ptr as *mut P::Pointee) })
25}
26
27pub const unsafe fn fn_call<P, I, O>(
28) -> impl Fn(*const (), I) -> O + Copy + Send + Sync + UnwindSafe + RefUnwindSafe + Unpin + 'static
29where
30    P: PointerDeref,
31    P::Pointee: Fn(I) -> O,
32{
33    |erased_ptr, input| unsafe { (*(erased_ptr as *const P::Pointee))(input) }
34}
35
36pub const unsafe fn fn_call_mut<P, I, O>(
37) -> impl Fn(*mut (), I) -> O + Copy + Send + Sync + UnwindSafe + RefUnwindSafe + Unpin + 'static
38where
39    P: PointerDerefMut,
40    P::Pointee: FnMut(I) -> O,
41{
42    |erased_ptr, input| unsafe { (*(erased_ptr as *mut P::Pointee))(input) }
43}
44
45pub const unsafe fn fn_call_once<P, I, O>(
46) -> impl Fn(*mut (), I) -> O + Copy + Send + Sync + UnwindSafe + RefUnwindSafe + Unpin + 'static
47where
48    P: PointerIntoInner,
49    P::Pointee: FnOnce(I) -> O,
50{
51    |erased_ptr, input| (unsafe { P::from_ptr(erased_ptr as *mut P::Pointee) }).into_inner()(input)
52}
53
54pub const unsafe fn fn_poll_unforgotten<P, O>(
55) -> impl Fn(*mut (), &mut task::Context<'_>) -> task::Poll<O>
56       + Copy
57       + Send
58       + Sync
59       + UnwindSafe
60       + RefUnwindSafe
61       + Unpin
62       + 'static
63where
64    P: PointerPinUnforgotten,
65    P::Pointee: Future<Output = O>,
66{
67    |erased_ptr, cx| unsafe { (Pin::new_unchecked(&mut *(erased_ptr as *mut P::Pointee))).poll(cx) }
68}