Mutually recursive async functions disallowed even with dynamic frame allocation
This program complains that amain depends on itself. Although this program is an infinite loop that constantly leaks memory, my understanding is that this is not an illegal zig program. I had a less bad program with the same error, but this one is shorter.
const std = @import("std");
async fn f() void {}
fn recurse() !void {
const frame = try std.heap.direct_allocator.create(@Frame(amain));
frame.* = async amain();
try await frame;
}
pub fn amain() error{OutOfMemory}!void {
var bytes = try std.heap.direct_allocator.alignedAlloc(u8, 16, 0);
await @asyncCall(bytes, {}, f);
try recurse();
}
pub fn main() anyerror!void {
try amain();
}
The problem seems to be the recursive reference to the @Frame(...) type. As a partial workaround for now, you can use @asyncCall in enough places to break any @Frame-type cycles in the callgraph, using @frameSize rather than anything looking like @sizeOf(@Frame(...)) (which allocator.create is doing internally), and then you just need a big enough alignment for your buffer.
I'm not sure if there's a user-space way to get something like an alignment counterpart to @frameSize though. I bet std.Target.stack_align will always suffice, but that's only a hunch.