> unwillingness by language designers (or more likely implementors) to treat threading like GC
There is a technical reason behind this, it's not just style.
The async-await transformation is highly compatible with calling other things in the C environment and receiving callbacks from that environment.
In some implementations the async-await transformation converts nested async functions to stackless state machines that are compatible with the C environment assumed by other libraries (especially in other languages) and by the operating system.
But it does have some performance cost, compared with functions that can assume stack scope. That cost only appears when using functions labelled "async".
Making every function automatically async in this model is nicer syntax (imho) but adds that cost to every function, unless the compiler is able to do a more global analysis, or deviates from strong compatibility with the C environment.
Another approach is to transform them to system threads. Then you don't need the async-await transform and it's compatible with the C environment, but you lose performance in some types of program where async-await is used, and sometimes a lot of memory or address space. So there's still a cost. Especially on targets where threads aren't particularly well implemented.
Yet another is green threads or other C-compatible coroutine implementation. This costs some compatibility with the C environment on some targets, though. Switching stacks in C works almost everywhere, but not everywhere, and has portability issues. The standard library function to assist with stack switching has been removed from POSIX, but it was never particularly fast anyway.
Go gets around this by being willing to deviate more from the C environment. It goes hand in hand with the very self-contained nature of Go compiled programs. Java gets around this by being a JIT interpreter which is free to do a lot of things its own way inside the Java execution.