You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于结构体内部Sleep实现DelayedValue的Future trait遇Pin错误求助

解决封装Tokio Sleep Future时的Pin编译错误

我想要实现一个DelayedValue Future,让它在指定时长后返回目标值,于是打算封装Tokio crate里的Sleep Future,但遇到了Pin相关的编译错误,始终没法调用底层Sleep成员的poll方法。以下是体现需求但无法编译的代码:

use futures::task::{Context, Poll};
use futures::Future;
use std::pin::Pin;
use tokio::time::{sleep, Sleep, Duration};

struct DelayedValue<T> {
    value: T,
    sleep: Sleep,
}

impl<T> Future for DelayedValue<T> {
    type Output = T;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        match &mut self.sleep.poll(cx) {
            Poll::Ready(()) => Poll::Ready(self.value),
            x => x,
        }
    }
}

#[tokio::main]
async fn main() {
    let dv = DelayedValue {
        value: 10_u8,
        sleep: sleep(Duration::from_millis(5000)),
    };

    println!("waiting for delayed value");
    
    let v = dv.await;
    println!("delayed value: {}", v);
}

错误原因

  1. Sleep的poll方法要求调用者是Pin<&mut Sleep>,但直接通过self.sleep只能拿到&mut Sleep,没有被固定(Pin),不符合方法的参数要求。
  2. 当Sleep完成后,直接访问self.value会因为self是Pin<&mut Self>而无法直接获取所有权,违反Pin的安全规则。

修复后的代码

use futures::task::{Context, Poll};
use futures::Future;
use std::pin::Pin;
use tokio::time::{sleep, Sleep, Duration};

struct DelayedValue<T> {
    value: T,
    sleep: Sleep,
}

impl<T> Future for DelayedValue<T> {
    type Output = T;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        // 用map_mut获取Pin住的Sleep引用
        match self.map_mut(|s| &mut s.sleep).poll(cx) {
            Poll::Ready(()) => {
                // 当Sleep完成,取出内部的value
                Poll::Ready(Pin::into_inner(self).value)
            }
            Poll::Pending => Poll::Pending,
        }
    }
}

#[tokio::main]
async fn main() {
    let dv = DelayedValue {
        value: 10_u8,
        sleep: sleep(Duration::from_millis(1000)),
    };

    println!("waiting for delayed value");
    
    let v = dv.await;
    println!("delayed value: {}", v);
}

关键修改说明

  • 使用Pin::map_mut方法,将Pin<&mut DelayedValue<T>>转换为Pin<&mut Sleep>,满足Sleep::poll的参数要求。
  • 当Sleep完成后,调用Pin::into_inner将Pin<&mut Self>还原为&mut Self,此时可以安全取出value,因为Future已经完成,不会再被轮询(poll),不存在移动Pin值的风险。

运行这段代码后,程序会等待1秒,然后输出delayed value: 10,符合预期功能。

内容的提问来源于stack exchange,提问作者John Smith

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 23:50:28