While I agree with your post, I do want to call out that Rust’s standard library does use a lot of unstable features and calls compiler intrinsics. Anyone can use the unstable features I believe with just #![feature(...)], but not the intrinsics (not that there’s much reason to call the intrinsics directly anyway).



Breaking down what
async fnin trait does, it converts it to afn method() -> impl Future<Output=T>, which breaks further down intofn method() -> Self::__MethodRetwhere the generated associated type implementsFuture.This doesn’t work for
dyn Traitbecause of the associated type (and the factmethod()needs a dyn-safeselfparameter).Instead, your methods need to return
dyn Futurein some capacity since that return type doesn’t rely on associated types. That’s whereasync_traitcomes in.Box<dyn Future<...>>is a dyn-safe boxed future, then it’s pinned becauseasyncusually generates a self-referential type, and you need to pin it anyway to.poll()the resulting future.Edit: also, being pedantic, associated types are fine in dyn traits, but you need to specify the type for it (like
dyn Blah<Foo=i32>. Even if you could name the return type from anasync fn, it’d be different for everyimplblock, so that’s not realistic here.