If you've written a trait with an async method, implemented it for a couple of types, and then tried to throw them into a Vec>, you've probably seen this:
error[E0038]: the trait Notifier cannot be made into an object
It's jarring because the identical pattern works fine for sync traits. Add async to one method and object safety breaks entirely.
The root cause isn't a missing feature, it's structural. An async fn desugars into a state machine implementing Future, and that state machine's concrete type is anonymous and differently sized per implementor. A vtable needs a fixed-size, uniform entry per method across every possible implementor. Those two facts just don't reconcile, and the Rust compiler team has been explicit this isn't getting patched any time soon.
So what do you actually do about it? There are three legitimate workarounds, and the right one depends on whether your implementors are a closed set you control, an open set from third-party code, or you're building a library where the boxing cost matters to your downstream users.
I break down all three approaches with working code, a side-by-side cost comparison, and a decision table for picking the right one here: https://devencyclopedia.com/blog/rust-async-traits-object-safe
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.