Breaking down what async fn in trait does, it converts it to a fn method() -> impl Future<Output=T>, which breaks further down into fn method() -> Self::__MethodRet where the generated associated type implements Future.
This doesn't work for dyn Trait because of the associated type (and the fact method() needs a dyn-safe self parameter).
Instead, your methods need to return dyn Future in some capacity since that return type doesn't rely on associated types. That's where async_trait comes in. Box<dyn Future<...>> is a dyn-safe boxed future, then it's pinned because async usually 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 an async fn, it'd be different for every impl block, so that's not realistic here.