rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
99.18k stars 12.81k forks source link

Allow `Waker::from` to accept trait object `Arc<dyn Wake>` #132339

Open nurmohammed840 opened 1 month ago

nurmohammed840 commented 1 month ago

I don't know it this issue is duplicate.

Consider this code snippet

use std::{sync::Arc, task::{Wake, Waker}};

trait Foo: Send + Sync {}
impl Wake for dyn Foo {
    fn wake(self: Arc<Self>) {
        todo!()
    }
}

struct Object;
impl Foo for Object {}

fn main() {
    let foo = Arc::new(Object) as Arc<dyn Foo>;
    Waker::from(foo);
}

Currently this code doesn't work, Because Waker::from cannot be used with Arc<dyn Wake>

https://github.com/rust-lang/rust/blob/1e4f10ba6476e48a42a79b9f846a2d9366525b9e/library/alloc/src/task.rs#L109

It would be ideal if Waker::from could support W: ?Sized objects by relaxing the Sized bound on W.

bjorn3 commented 1 month ago

There is no place to store the vtable for Arc<dyn Wake> inside the RawWaker. The vtable field of RawWaker is already taken by a vtable whose contents are statically known for any given type passed to impl From<Arc<W>> for Waker: https://github.com/rust-lang/rust/blob/1e4f10ba6476e48a42a79b9f846a2d9366525b9e/library/alloc/src/task.rs#L173-L176 The comment above this function explains a bit why this is the case: https://github.com/rust-lang/rust/blob/1e4f10ba6476e48a42a79b9f846a2d9366525b9e/library/alloc/src/task.rs#L130-L134 I don't know if this is just a precaution thing or if it actually matters for safety. In any case relaxing the ?Sized bound would also technically allow Arc<[T]> to be converted to a Waker, for which there is no valid vtable we can create without allocating memory.