Earlier quoted context omitted.
"Ergonomic" is such a nebulous word as to be nearly useless honestly. I don't see how it is [unduly] inefficient or uncomfortable for a language at Rust's level to ensure that the programmer actually thinks through the execution of the code they are writing. If one doesn't want to think about such things - and there's absolutely nothing wrong with that! - there are plenty of higher level languages that can do that le…
The whole point of async is entirely ergonomics. Anything you can do in async you can do in continuation-passing style. I believe the point the author is making is that they added a feature for ergonomics' sake that ended up not being ergonomic; async-style programming usually coincides with first-class functions and closures, and those are painful in Rust.
Are they, though?
The example the author gives in the article tries to write a multithreaded program as if it is a singlethreaded one. Of course that is going to be painful, whether you're trying to use futures/promises or you're using callbacks. If you want to use multiple threads safely (i.e. at all) you need to use the right structures for the job - smart pointers, mutexes, etc. This is independent of language really, even dynamically typed languages like Ruby still have mutexes for when you want to use multiple threads (though they do take control away from the programmer in the form of things like global interpreter locks).
If you don't actually want to deal with the complexities of multithreading, then don't use it. For example there are a good number of languages/runtimes that only expose a single-threaded event loop to the programmer (even though they may use thread pools in the background). But I don't think "ergonomic" should necessarily mean "abstract away every single detail" or "things should Just Work even though one is straight-up not approaching the problem correctly".