为什么 Rust async 会强制实施者为 `Waker` 使用动态调度

Why is rust async forcing the implementors to use dynamic dispatch for `Waker`

我读到 async/await 是如何 implemented 生锈的,我注意到 RawWaker 本质上是一个胖指针。我不太明白为什么 Waker 的实现本质上类似于 struct Waker{data: *const (), vtable: *const WakerVTable} 而不是 Waker<T: Wakes>{raw_walker: &mut T} 这将使编译器知道 wake()wake_ref() 的实现, drop()clone() 在编译时。

唤醒者需要非常多才多艺。 This blog 解释了很多关于设计选择的内容,值得一读。相关部分是这样说的:

The only requirement that the poll phase introduces is dynamism: because it needs to be passed through arbitrary futures, the waker type cannot be generic. This means that every requirement introduced by the other two phases needs to be dynamically dispatched.

现在作者在这里不清楚的部分是“任意期货”包括 boxed futures(以及通常可以使用动态调度轮询的期货)。如果未来特征的定义如下:

pub trait Future {
    type Output;

    fn poll<W: Wake>(
        self: Pin<&mut Self>,
        cx: &mut Context<'_, W>,
    ) -> Poll<Self::Output>;
}

那么 trait Future 就不会是 object safe,排除了动态调度的可能性,即 deal-breaker.