rust - 如何固定投影向量的元素?

标签 rust future rust-pin

由于从向量中提取的元素未实现Pin <>类型,因此以下代码无法编译。
错误出现在ele.poll()调用中

#[pin_project]
pub struct FifoCompletions<T, F>
where
    F: Future<Output = Result<T, Error>>
{
    #[pin]
    pending: VecDeque<F>,
}

impl <T, F> FifoCompletions<T, F>
where
    F: Future<Output = Result<T, Error>>
{
    pub fn push(&mut self, f: F) {
        self.pending.push_back(f);
    }
}

impl <T, F> Future for FifoCompletions<T, F>
where
    F: Future<Output = Result<T, Error>>
{
    type Output = Result<T, Error>;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        let this = self.project();
        while !this.pending.is_empty() {
            match this.pending.front_mut() {
                None => unreachable!(),
                Some(ele) => {
                    let output = ready!(ele.poll(cx));
                }
            }

        }
        Poll::Pending
    }
}
错误消息是
no method named `poll` found for mutable reference `&mut F` in the current scope

method not found in `&mut F`

help: items from traits can only be used if the type parameter is bounded by the traitrustc(E0599)
sm.rs(66, 45): method not found in `&mut F`

最佳答案

这是您的问题的字面答案:

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

pub struct Completions<F>
where
    F: Future<Output = ()>,
{
    pending: Vec<F>,
}

impl<F> Future for Completions<F>
where
    F: Future<Output = ()>,
{
    type Output = ();

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        // I copied this from Stack Overflow without reading the prose
        // that describes why this is or is not safe.
        // ... It's probably not safe.
        let first = unsafe { self.map_unchecked_mut(|this| &mut this.pending[0]) };
        first.poll(cx)
    }
}
但是,这很可能是不安全,并引入了未定义行为。问题在于requirements for pinning复杂且细微。具体来说,一旦固定,值就永远不会在内存中移动,包括删除时。从文档中,重点是:

This can be tricky, as witnessed by VecDeque<T>: the destructor of VecDeque<T> can fail to call drop on all elements if one of the destructors panics. This violates the Drop guarantee, because it can lead to elements being deallocated without their destructor being called. (VecDeque<T> has no pinning projections, so this does not cause unsoundness.)


我与pin-project crate的作者taiki-e核对了。轻描淡写的报价:

Operations such as Vec(Deque)'s push, insert, remove, etc. can move elements. If you want to pin elements, these methods should not be called without Unpin after they have been pinned. The pin API actually blocks this.

If the destructor moves elements, it is unsound to pin the element returned by accessors like get_mut, front_mut without Unpin.

Make the element Unpin or use a collection that can handle !Unpin futures like FutureUnordered instead of VecDeque.


直接应用,最安全的方法是:
use pin_project::pin_project; // 1.0
use std::{
    future::Future,
    pin::Pin,
    task::{Context, Poll},
};

#[pin_project]
pub struct Completions<F>
where
    F: Unpin,
    F: Future<Output = ()>,
{
    #[pin]
    pending: Vec<F>,
}

impl<F> Future for Completions<F>
where
    F: Unpin,
    F: Future<Output = ()>,
{
    type Output = ();

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        let this = self.project();
        let pending = this.pending.get_mut();
        let first = Pin::new(&mut pending[0]);
        first.poll(cx)
    }
}
也可以看看:
  • No method named `poll` found for a type that implements `Future`
  • When is it safe to move a member value out of a pinned future?
  • 关于rust - 如何固定投影向量的元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64796290/

    相关文章:

    rust - 没有 `pin_project`的 `Unpin`声音如何

    unit-testing - Cargo 未在顶级文件中运行测试

    macos - Rust、OpenSSL、solana-test-validator 库未加载问题

    rust - 移动变量时会逐字节复制数据吗?

    java - 如何获得Completablefuture的结果

    generics - 有什么方法可以让 Rust 理解 `fn(T) -> impl Future` 总是返回相同的类型?

    rust - 在哪里可以找到我项目的 Rust 测试二进制文件?

    flutter - 从Flutter中的Firestore检索数据后为空列表

    rust - 如何使用具有自引用结构的 Pin 结构?

    rust - 在让 C++ 通过指针调用 Rust 方法时,我应该使用 Pin 吗?