php_tokio/
borrow_unchecked.rs

1// Borrowed from https://github.com/jeremyBanks/you-can
2
3// What's going on here? Unsafe borrows???
4// NO: this is actually 100% safe, and here's why.
5//
6// This is needed because of https://github.com/danog/php-tokio/blob/master/src/event_loop.rs#L72
7//
8// Rust thinks we're Sending the Future to another thread (tokio's event loop),
9// where it may be used even after its lifetime expires in the main (PHP) thread.
10//
11// In reality, the Future is only used by Tokio until the result is ready.
12//
13// Rust does not understand that when we suspend the current fiber in suspend_on,
14// we basically keep alive the the entire stack,
15// including the Rust stack and the Future on it, until the result of the future is ready.
16//
17// Once the result of the Future is ready, tokio doesn't need it anymore,
18// the suspend_on function is resumed, and we safely drop the Future upon exiting.
19
20use ext_php_rs::binary_slice::{BinarySlice, PackSlice};
21
22#[inline(always)]
23pub unsafe fn borrow_unchecked<
24    'original,
25    'unbounded,
26    Ref: BorrowUnchecked<'original, 'unbounded>,
27>(
28    reference: Ref,
29) -> Ref::Unbounded {
30    unsafe { BorrowUnchecked::borrow_unchecked(reference) }
31}
32
33#[doc(hidden)]
34pub unsafe trait BorrowUnchecked<'original, 'unbounded> {
35    type Unbounded;
36
37    unsafe fn borrow_unchecked(self) -> Self::Unbounded;
38}
39
40unsafe impl<'original, 'unbounded, T: 'unbounded> BorrowUnchecked<'original, 'unbounded>
41    for &'original T
42{
43    type Unbounded = &'unbounded T;
44
45    #[inline(always)]
46    unsafe fn borrow_unchecked(self) -> Self::Unbounded {
47        unsafe { ::core::mem::transmute(self) }
48    }
49}
50
51unsafe impl<'original, 'unbounded, T: 'unbounded> BorrowUnchecked<'original, 'unbounded>
52    for &'original mut T
53{
54    type Unbounded = &'unbounded mut T;
55
56    #[inline(always)]
57    unsafe fn borrow_unchecked(self) -> Self::Unbounded {
58        unsafe { ::core::mem::transmute(self) }
59    }
60}
61
62unsafe impl<'original, 'unbounded, T: 'unbounded + PackSlice> BorrowUnchecked<'original, 'unbounded>
63    for BinarySlice<'original, T>
64{
65    type Unbounded = BinarySlice<'unbounded, T>;
66
67    #[inline(always)]
68    unsafe fn borrow_unchecked(self) -> Self::Unbounded {
69        unsafe { ::core::mem::transmute(self) }
70    }
71}