There seems to be a defect in the type inference. In TFA's programs, using (but not calling) red gets you a value of the wrong type. Adding an explicit callconv(.Async) to red causes you to get this error:
./src/main.zig:42:32: error: expected type 'fn(*u64) void', found 'fn(*u64) callconv(.Async) void'
const fns = [2]@TypeOf(blue) { red, blue };
After that, changing the array to be an array of @TypeOf(red) gets you a working program. That is, it's apparently fine to store blue in a value of red's type and use blue with @asyncCall as if it was red's type at runtime, but trying to store red in a variable of blue's type is a compile error.
here's a gist demonstrating this stuff that a user posted in the Zig Discord: https://gist.github.com/sharpobject/49bd88416e68606d7812d609...
Hmm, seems like it’s maybe not in type inference per se. It seems more like the compiler actually believes that red (used as a function pointer) is not async! So it has the wrong type in @TypeOf and it also coerces itself with no warning to that wrong type. Ouch.
The docs are light on details, but the compiler should figure out that red is async, and it does if you call it, but not if you take a pointer. I would describe this as a defect! We don't actually disagree about any facts though, just labels.