Something which bothers me about coroutines is the pure boilerplate -- I don't even mean the ridiculous verbose coroutine definitions in C++20 but just the spread of "await" and "async" keywords all over the code, for instance in Python and Rust. I understand that these keywords are the compromise to introduce the feature into the language without paying for it when not using it, but I wonder if there is not a more concise way. Something not mentioned at all in the particle is the "what color is your function" problem (https://journal.stuffwithstuff.com/2015/02/01/what-color-is-...) where I wonder whether there is a good solution.
Those aren't actual symmetrical coroutines though. Try the raw greenlet python module. A coroutine can yield to an arbitrary coroutine and not just to the event loop.
I am always disappointed they didn't go all the way and made async/await syntactic sugar for a general Monad abstraction, like in Haskell.
And I like the Haskell do-blocks.