实现`std :: marker :: Unpin`是否安全?

时间:2019-12-21 15:25:09

标签: rust future

我准备将一些代码从Futures-0.1转换为Futures-0.3,其中poll()方法现在需要固定数据。我的某些结构无法固定,这使移植变得复杂。但是,似乎存在一种简单的方法,可以为这些类添加一个impl Unpin。这样安全吗?有哪些替代方案?

示例代码:

extern crate futures;

use std::future::Future;
use std::pin::Pin;
use std::task::{ Poll, Context };

struct InnerData {
    _pin: std::marker::PhantomPinned,
}

struct Stream {
}

struct Poller {
    _data: InnerData,
    file: Stream,
}

impl futures::stream::Stream for Stream {
    type Item = ();

    fn poll_next(self: Pin<&mut Self>, _cx: &mut Context) -> Poll<Option<Self::Item>> {
        Poll::Pending
    }
}

impl Future for Poller {
    type Output = Result<(), ()>;

    fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output>
    {
        use crate::futures::Stream;

        // here, rust fails with
        // error[E0277]: the trait bound `std::marker::PhantomPinned: std::marker::Unpin` is not satisfied in `Poller`  
        Pin::new(&mut self.get_mut().file).poll_next(cx).is_ready();

        Poll::Pending
    }
}

// Activating this seems to be an easy workaround...
// impl std::marker::Unpin for Poller {}

fn main() {
}

我使用futures-0.3.1rust-1.40.0

1 个答案:

答案 0 :(得分:0)

  

这样安全吗?

是的,因为将Poller标记为Unpin就其字段而言不是可传递的。您仍然无法凭空想到一个固定的_data字段。如果您尝试Pin::new(&mut self.get_mut()._data)会导致编译器错误,因为new仅在Pin<P><P as Deref>::Target时才可用于Unpin

impl<P> Pin<P> where
    P: Deref,
    <P as Deref>::Target: Unpin,
{
    pub fn new(pointer: P) -> Pin<P>
}

Rust Pin documentation的一个部分对此进行了扩展:

  

对于field,钉扎不是结构性的

     

当从未创建过Pin<&mut Field>时,该类型对固定的想法就无关紧要。

只有执行impl std::marker::Unpin for InnerData {}才是不安全的,这会向编译器承诺不正确的内容。它将无法阻止您再写Pin::new(&mut self.get_mut()._data)

这可行:

impl Future for Poller {
    fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
        use futures::stream::Stream as _;
        Pin::new(&mut self.get_mut().file).poll_next(cx).is_ready();
        Poll::Pending
    }
}

impl std::marker::Unpin for Poller {}
  

有哪些替代方案?

有些{@ {1}}这样的第三方板条箱可以使此pin-project业务变得更轻松:

Pin
相关问题