Rust 的 Future 缺失状态:poll 之后还能再调吗?
原创Rust 的 Future 缺失状态:poll 之后还能再调吗?
MaybeDone 与缺失的状态
在 async Rust 里,Future::poll 是推进 future 状态的唯一入口。它返回 Poll 枚举,两个变体:Pending 表示还没准备好,稍后要再调;Ready(T) 表示就绪了,能产出值 T。文档说一个 future 只产一个值,但 stdlib 没把这句话写死。作者 Yosh Wuyts 在 2026 年 10 月写的这篇博客,就是想说:这个“值”是单数,但 poll 的调用次数没被约束住。stdlib 文档没有明确做出这个保证,生态里也不是总实现得对。来源:BW
文档对重调用写得很明白:“Once a future has completed (returned Ready from poll), calling its poll method again may panic, block forever, or cause other kinds of problems; the Future trait places no requirements on the effects of such a call.” 意思是 poll 返回 Ready 之后你再调一次,行为没保证,无非 panic、死锁或别的问题。最常见的是 panic!,所有 async block 和 async fn 生成的 future 都这样。作者说这很可惜,他经常想“已经 Ready 过了,能不能再 poll 一次”,比如拿到值之后还想知道 future 是不是还活着。作者说能这样调“is actually quite useful and something I frequently wish I was able to do”,这是他写这篇博客的动机。来源:BW
MaybeDone 是个简单包装器,专门处理这个场景。它要么持有 Future 本身,要么持有已经完成的 Future::Output。它的 Done 变体是 Option,为什么要包 Option?因为要表示“值已经被拿走”这个状态。但问题在于,MaybeDone 只区分“未完成”(Future)和“已完成”(Done),它没有第三个状态去表达“已就绪但值已被取走”。作者在代码里用 pin_project 宏定义了这个枚举,结构清楚,但缺的状态也清楚。来源:BW
所以实际写并发原语时,比如 join! 或 select! 宏,实现者必须在 Done 状态里再额外判断 Option 是否被 take 过,或者干脆依赖 panic! 来防重调用。作者说这些实现者“will be familiar with the MaybeDone type”,但熟悉归熟悉,这个类型缺的状态,让代码变复杂,也让错误风险变高。作者甚至说“not everyone writing Rust writes async Rust”,但写并发原语的人躲不开它。来源:BW
poll 重调用的生态缺口
作者把这个问题上升到 Future trait 层面。标题直接写“The Future Trait Has a Missing State”,说的是 Future trait 本身缺一个显式状态,表达“已经 Ready 但值被取走”。如果 trait 里有这个状态,MaybeDone 就不用靠 Option 兜底,poll 重调用也能被安全处理。但文档现在明说“no requirements on the effects”,这等于把责任推给了实现者。来源:BW
生态里不是每个人都写 async,也不是每个 async 开发者都写并发原语。但写原语的人,比如 tokio 的 join!、futures 的 select!,都绕不开 MaybeDone 这个坑。作者说“those who do will be familiar”,语气里带着无奈。明明是个简单包装器,却因为缺一个状态,让实现者要么接受 panic,要么自己加标志位。来源:BW
我不确定这个缺失状态会不会在 future 版本里被补上。stdlib 文档说“should”make this guarantee,作者说“though it should”,都是虚词。但有一点是实的,poll 之后不能再调,让很多合理用法变得不安全。MaybeDone 的 Done(Option) 就是为这个妥协设计的,而妥协本身,就是缺口存在的证据。来源:BW
原文:
The Future Trait Has a Missing State · 来源:Hacker News
作者:itfan123 值班编辑 · 发布于 2026年10月29日
版权声明
所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除
itfan123





