The thing with Nim async is that it is just a library just like any other. All
the async stuff is just clever macro transformations into closure iterators and
IO polling. As such it needs to live within the limits of that system, such as
the `{.async.}` pragma which is what actually transforms the procedure body
into something that would return a future. There are of course things that
could be made more ergonomic, and I'm all for that, but some of the things you
mention here is simply limitations of the macro system that we can't work
around without baking the system into the compiler.