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

存储参数化Future的Timeout结构体时遇编译错误:大小无法确定

关于Tokio Timeout存储到自定义结构体的编译问题

我尝试将tokio::Timeout结构体存储到自定义结构体SockTimeout中,让该结构体拥有它的所有权。我注意到Timeout<T>带有Sized约束,但原以为Timeout能满足编译器要求。

代码示例

use std::future::Future;
use std::time::Duration;
use tokio::time::{error::Elapsed, timeout, Timeout};

struct SockTimeout {
    pub timeout: Timeout<dyn Future<Output = ()>>,
}

#[tokio::main]
async fn main() {
    let when = Duration::from_millis(2000);

    let my_struct = SockTimeout {
        timeout: timeout(when, async {}),
    };
}

编译错误

error[E0277]: the size for values of type `(dyn Future<Output = ()> + 'static)` cannot be known at compilation time
   --> src/main.rs:30:18
    |
30  |     pub timeout: Timeout<dyn Future<Output = ()>>,
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `(dyn Future<Output = ()> + 'static)`
note: required by a bound in `tokio::time::Timeout`
   --> /Users/steve/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-1.19.2/src/time/timeout.rs:135:24
    |
135 |     pub struct Timeout<T> {
    |                        ^ required by this bound in `tokio::time::Timeout`

问题分析与解决方案

你忽略的核心点是:Timeout<T>的泛型参数T必须满足Sized约束,而dyn Future<Output = ()>是动态大小类型(DST),它的大小在编译时无法确定,自然不满足Sized。你之前尝试用Box包装Timeout本身没用,因为问题出在Timeout内部的T是DST,不是Timeout结构体本身的大小。

解决方法有两种:

1. 用Box包装内部的Future,让T变成Sized类型

把Timeout的泛型参数换成Box<dyn Future<Output = ()>>,因为Box<T>是大小固定的指针类型,满足Sized。同时注意Tokio的timeout要求传入的Future实现Unpin,所以需要用Box::pin包装异步块:

use std::future::Future;
use std::time::Duration;
use tokio::time::{timeout, Timeout};

struct SockTimeout {
    pub timeout: Timeout<Box<dyn Future<Output = ()> + 'static>>,
}

#[tokio::main]
async fn main() {
    let when = Duration::from_millis(2000);

    let my_struct = SockTimeout {
        timeout: timeout(when, Box::pin(async {})),
    };
}

2. 将SockTimeout定义为泛型结构体

通过让SockTimeout携带泛型参数,保留Future的具体类型,这样T自然满足Sized,这种方式没有动态分发的开销:

use std::future::Future;
use std::time::Duration;
use tokio::time::{timeout, Timeout};

struct SockTimeout<T>
where
    T: Future<Output = ()> + 'static,
{
    pub timeout: Timeout<T>,
}

#[tokio::main]
async fn main() {
    let when = Duration::from_millis(2000);

    let my_struct = SockTimeout {
        timeout: timeout(when, async {}),
    };
}

内容的提问来源于stack exchange,提问作者Steve McFarlin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 13:27:18