gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-03 11:47:26 25 4
gpt4 key购买 nike

由于从向量中提取的元素未实现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/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com