That way you could pass around IntoFutures without being affected by auto traits leaking. Only when you actually call .await() or .poll() would the immovable Future materialize.
Since it's just a matter of how async get desugared, can it be changed through an edition?
To dump some ideas on you: I think one missing piece might be that FnOnce() -> impl Future should implement IntoFuture. Async runtimes would then use IntoFuture in their APIs agressively.
I call this a "workload blueprint" at work. Its a closure/type that contains all the info to start the workload, but in a minimal form. In Rust terms this would be a buildprint that is ideally Send + Move + Forget + 'static, even if the actual work (and the backing struct of the Future) is !Send (e.g. It holds an Rc across await points).
Runtimes could use this for their advantage: There would be a global pool of "workload blueprint" that can be stolen by any executer thread, but once a !Send workload has started on one thread it can't be migrated to another.
This in combination with matklad's ideas about seperating TaskSend from ThreadSend (https://matklad.github.io/2023/12/10/nsfw.html) would solve most of my async pain points.