That is an unfair characterization of Zig. The OP correctly points out:

> Function signatures don’t change based on how they’re scheduled, and async/await become library functions rather than language keywords.

The functions have the same calling conventions regardless of IO implementation. Functions return data and not promises, callbacks, or futures. Dependency injection is not function coloring.

> The functions have the same calling conventions regardless of IO implementation.

Okay, then by that definition, Rust doesn't have colored functions either, because `async fn foo() -> Bar {` in Rust is just syntax sugar for `fn foo() -> impl Future<Output=Bar> {` (that's a normal function that returns a future), and `Future` is just a normal trait that provides a `poll` method; there's no different calling convention anywhere. So which is it? Either Rust and Zig both have colored functions, or neither do.

These things _are_ function colouring, but they show function colouring isn't scary or hard.

The original function colouring essay was much more about JavaScript's implementation than a general statement.

If JavaScript had exposed a way for a synchronous function to call back into the runtime to wait for an async function to complete, it would still be just as coloured, but no one would be complaining about colour (deadlocks yes, but that's another kettle of fish).