You can create `Io` instances whenever you want (although that kinda goes against its spirit) and you can also pass them inside structs, not necessarily as a function argument. Moreover you can reuse all the existing "sync" functions when using I/O and viceversa (ever tried doing an async call inside a `Option::map` in Rust?)
By the way, Rust's runtime also have a similar issue to Zig's `Io` (making the runtime available to the code, similarly to how you need to make an `Io` instance available in Zig). Rust runtimes just decided to use thread locals for that, and nothing stops you from doing the same in Zig if you want to.
I hope you can see that this is all orthogonal to the "colored functions" problem. When I was talking about tradeoffs however I was referring to the use of a threaded/green thread implementation under the hood as opposed to a stackless coroutine. The first two are less invasive at the language level and don't require function coloring (hence why Zig didn't solve, but also doesn't have, function coloring!) however they can be more limiting (they are not always available, especially on embedded and on wasm) and less extensible (most operations need to be explicitly supported in `Io`, as opposed to being implementable by anyone).
By the way, Rust's runtime also have a similar issue to Zig's `Io` (making the runtime available to the code, similarly to how you need to make an `Io` instance available in Zig). Rust runtimes just decided to use thread locals for that, and nothing stops you from doing the same in Zig if you want to.
I hope you can see that this is all orthogonal to the "colored functions" problem. When I was talking about tradeoffs however I was referring to the use of a threaded/green thread implementation under the hood as opposed to a stackless coroutine. The first two are less invasive at the language level and don't require function coloring (hence why Zig didn't solve, but also doesn't have, function coloring!) however they can be more limiting (they are not always available, especially on embedded and on wasm) and less extensible (most operations need to be explicitly supported in `Io`, as opposed to being implementable by anyone).