Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dyn real_async_trait? #6

Open
eholk opened this issue Mar 16, 2022 · 2 comments
Open

dyn real_async_trait? #6

eholk opened this issue Mar 16, 2022 · 2 comments

Comments

@eholk
Copy link
Contributor

eholk commented Mar 16, 2022

Is there a way to make a dyn Trait object out of a type that impls a trait annotated with #[real_async_trait]?

I'd like to be able to do something like:

#[real_async_trait]
trait Foo {
    async fn foo();
}

struct Bar {
    maybe_foo: Option<Box<dyn Foo>>,
}

When I try to do this, however, I get an error saying I need to specify the associated type for Foo::foo.

@4lDO2
Copy link
Owner

4lDO2 commented Jun 11, 2022

Well, since every implementation gets its own future types, no real-async-trait traits are object safe unless you box the futures, which you cannot guarantee every implementation will do. It should in theory be possible to require that the futures be boxed when creating an async trait object and hence be the same size and thereby object safe (like the regular async-trait crate does), but it's nontrivial and we might have to wait for the language to implement async traits first. Or, we can manually generate code for both an object safe trait and a regular trait, and then implement the regular trait for types which already implement the object safe trait. But AFAIK the only way now to make dyn async traits is to use async-trait.

@eholk
Copy link
Contributor Author

eholk commented Jun 20, 2022

We could probably do this by having real_async_trait generate a bridge trait, although perhaps opt-in with something like #[real_async_trait(dyn)]. In my example, we'd generate something like this to go with it:

trait DynFoo {
    fn foo(&self) -> Box<dyn Future<Output = ()>>;
}

impl<T: Foo> DynFoo for T {
    fn foo(&self) -> Box<dyn Future<Output = ()>> {
        Box::new(<Self as Foo>::foo(self))
    }
}

Although until there's more language support if you need this then using async-trait is probably the best option.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants