When looking at std::pin::Pin it seemed that following operations should be safe - narrowing scope, converting &mut T
into Pin<&mut T>
and pin pattern matching.
struct Map<F, G> {
future: F,
func: Option<G>
}
impl<F, G, B> Future for Map<F,G>
where
F: Future,
G: FnOnce(Future::Output) -> B + Unpin
{
type Output = B;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>
{
// future: Pin<&mut F>
// func: &Option<FnOnce(Future::Output) -> B>
// To have lack of pin it needs to be Unpin
let Map {pin ref mut future, ref mut func} = self;
match future.poll(cx) {
Ready(value) => Ready(func.take().expect("Map value already consumed")(value)),
Pending => Pending.
}
}
}
Converting &mut T
into Pin<&mut T>
- since &mut T
is an exclusive reference to T
any access to T
needs to be done by this reference. So we can temporarily pin it as we know no-one will move the value from underneath us:
impl<'a, T> Pin<&'a mut T> {
pub fn new_from_mut(&'a mut T) -> Self;
}
Narrowing scope (Pin is contravariant in scope):
impl<'a> Pin<&'a T> {
fn narrow<'b>(&'mut self) -> Pin<&'b T> where 'a: 'b
}
If data is unmovable in larger scope it is also unmovable in smaller scope.
Pattern matching - currently field access is under unsafe
. However this seems to be unnecessarily restrictive. However we already have a pattern matching on references so pin
might make sense:
struct FlatMap<F, G, H> {
BeforeF(F, Option<G>),
BeforeH(H)
}
impl<B> Future for FlatMap<B, F, G, H>
where
F: Future<Output = B>,
G: FnOnce(B) -> H + Unpin,
H: Future
where
{
type Output = H::Output;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>
{
let new_h_opt = if let FlatMap::BeforeF(pin ref mut future, ref mut func) = self.narrow() {
match future.poll(cx) {
Ready(value) => Some(func.take().unwrap()(value)),
Pending => return Pending;
}
} else {
None
};
if let Some(new_h) = new_h_opt {
self.set(FlatMap::BeforeH(new_h));
}
if let FlatMap::BeforeH(pin ref mut future) {
future.poll(cx)
} else {
unreachable!()
}
}
}
I don't see any related proposals and my (very basic) understanding of Pin
indicates those operations should be safe