-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Stage2: false dependency loop #12325
Comments
This also fails: pub const DeviceCallback = *const fn (*Device) void;
pub const Device = struct {
callback: DeviceCallback,
};
test {
_ = DeviceCallback;
} error: dependency loop detected @Vexu Do you think this is the same bug or should I open a new issue? |
It's the same bug. |
Slight variation on this issue, this example straight-up crashes the compiler: const Foo = struct {
ptr: *[1]Foo,
};
test {
const x: Foo = undefined;
_ = x;
} Weirdly, |
That is a separate bug in the LLVM backend's debug info creation, adding either |
Ah okay, thank you. Is there an open issue for that bug (just so I can reference it in a comment)? |
Not that I know of. |
Note as a workaround for this I'm just hand-modifying the cimport.zig to just replace the pointers with anyopaque pointers. I've only had this issue with C imports (probably due to the style of C this sort of reference is common -- I know you can get this in pure Zig too I just haven't seen or written code in practice that does). This works for now! |
The following also fails: const std = @import("std");
const node_size = 16;
const Tag = enum(u8) {
none,
some
};
pub const Maybe = extern union {
none: extern struct {
tag: Tag = .none,
padding: [node_size - @sizeOf(Tag)]u8 = undefined,
},
some: Some,
};
const Body = extern struct {
maybe: Maybe = Maybe{.none = .{}},
};
const Some = extern struct {
const padding_len = node_size - (@sizeOf(Tag) + @sizeOf(usize));
tag: Tag = .some,
padding: [padding_len]u8 = [_]u8{0} ** padding_len,
body: *Body,
};
pub fn main() !void {
std.debug.print("{any}\n", .{@sizeOf(Maybe)});
} Interestingly when |
That looks very similar to my original case that I was unable to reduce. |
this is sadly blocked on ziglang/zig#12325
This includes workarounds for ziglang/zig#12325 issue by using `*anyopaque` instead of `*T` and casting the function pointers.
Main problem is ziglang/zig#12325 which forces me to use *anyopaque pointers and waste time casting them back to their actual type and possibly slowing things down because of the added pointer alignment check
Main problem is ziglang/zig#12325 which forces me to use *anyopaque pointers and waste time casting them back to their actual type and possibly slowing things down because of the added pointer alignment check
Main problem is ziglang/zig#12325 which forces me to use *anyopaque pointers and waste time casting them back to their actual type and possibly slowing things down because of the added pointer alignment check closes #97
i'm having a similar issue. is this the same thing? if not is there already an issue for this or should i make a one? really wanting this feature for generated code in my protobuf-zig lib so that i don't have to resort to generating duplicate .c,/h files to achieve this. // /tmp/tmp.zig
pub const A = extern struct { // same happens w/ non-extern struct
b: *const B,
};
pub const B = extern struct {
a: *const A,
};
const a = A{ .b = &b };
const b = B{ .a = &a };
test {
_ = a;
} $ zig test /tmp/tmp.zig
/tmp/tmp.zig:11:1: error: dependency loop detected
const a = A{ .b = &b };
^~~~~~~~~~~~~~~~~~~~~~ |
This issue is about types incorrectly depending on themselves while yours is caused by declarations depending on each others address recursively and reduces to: const a = &b;
const b = &a;
test {
_ = a;
} |
Thanks. Created #14517 |
I hit this as well, in basically the same situation. Eventually I resorted to using pub const DeviceCallback = *const fn (*anyopaque) void;
fn someCallback(p: *anyopaque) void {
const device: *Device = @ptrCast(@alignCast(p));
} |
Implement audio playback, hopefully motivation is self explanatory The audio landscape is vast in linux, we have alsa, pulse, jack, pipewire and alsa, pulse, jack interfaces into pipewire, alsa interfaces into pulse, etc. Instead of trying to deal with this ourselves, pull in an audio lib to deal with it for us Just skimming online, miniaudio fits well. PortAudio and libsoundio also seem to both be good candidates. No strong reasoning went into this choice, the single header impl of miniaudio felt easy to work with. We were tricked though, with the default miniaudio impl we hit a zig compiler bug that triggers circular dependencies. Something about using a struct pointer in a function pointer stored by the struct, see ziglang/zig#18247 (comment) Patch miniaudio to just use void pointers instead, this doesn't seem to have any negative effects Add an audio player abstraction that just injects a sin wave for now, add test binary to try it Potentially related issues... ziglang/zig#12325 ziglang/zig#16419
Implement audio playback, hopefully motivation is self explanatory The audio landscape is vast in linux, we have alsa, pulse, jack, pipewire and alsa, pulse, jack interfaces into pipewire, alsa interfaces into pulse, etc. Instead of trying to deal with this ourselves, pull in an audio lib to deal with it for us Just skimming online, miniaudio fits well. PortAudio and libsoundio also seem to both be good candidates. No strong reasoning went into this choice, the single header impl of miniaudio felt easy to work with. We were tricked though, with the default miniaudio impl we hit a zig compiler bug that triggers circular dependencies. Something about using a struct pointer in a function pointer stored by the struct, see ziglang/zig#18247 (comment) Patch miniaudio to just use void pointers instead, this doesn't seem to have any negative effects Add an audio player abstraction that just injects a sin wave for now, add test binary to try it Potentially related issues... ziglang/zig#12325 ziglang/zig#16419 ziglang/zig#19392
Implement audio playback, hopefully motivation is self explanatory The audio landscape is vast in linux, we have alsa, pulse, jack, pipewire and alsa, pulse, jack interfaces into pipewire, alsa interfaces into pulse, etc. Instead of trying to deal with this ourselves, pull in an audio lib to deal with it for us Just skimming online, miniaudio fits well. PortAudio and libsoundio also seem to both be good candidates. No strong reasoning went into this choice, the single header impl of miniaudio felt easy to work with. We were tricked though, with the default miniaudio impl we hit a zig compiler bug that triggers circular dependencies. Something about using a struct pointer in a function pointer stored by the struct, see ziglang/zig#18247 (comment) Patch miniaudio to just use void pointers instead, this doesn't seem to have any negative effects Extract audio frames from ffmepg, and feed them into our audio subsystem. Not a ton to say here, everything is just using the APIs provided by miniaudio and ffmpeg Replace test video with a 20s segment of big buck bunny Potentially related issues... ziglang/zig#12325 ziglang/zig#16419 ziglang/zig#19392
Just in case, one more example. This one does not compile: const std = @import("std");
const Foo = struct {
const FnPtr = *const fn (*Foo, u8) void;
data: u8,
cb: FooCallBack,
const FooCallBack = struct {
fptr: FnPtr,
data: u8,
};
fn init(fptr: FnPtr) Foo {
return .{
.data = 7,
.cb = .{.fptr = fptr, .data = 8},
};
}
fn call(foo: *Foo, data: u8) void {
foo.cb.fptr(foo, data);
}
};
fn bar(foo: *Foo, data: u8) void {
std.debug.print (
"data-1 = {}, data-2 = {}, data-3 = {}\n",
.{foo.data, foo.cb.data, data}
);
}
pub fn main() !void {
var foo = Foo.init(&bar);
foo.call(9);
} Get
But this one (without "construtor") compiles: const std = @import("std");
const Foo = struct {
const FnPtr = *const fn (*Foo, u8) void;
data: u8,
cb: FooCallBack,
const FooCallBack = struct {
fptr: FnPtr,
data: u8,
};
pub fn call(foo: *Foo, data: u8) void {
foo.cb.fptr(foo, data);
}
};
fn bar(foo: *Foo, data: u8) void {
std.debug.print (
"data-1 = {}, data-2 = {}, data-3 = {}\n",
.{foo.data, foo.cb.data, data}
);
}
pub fn main() !void {
var foo: Foo = .{
.data = 7,
.cb = .{.fptr = &bar, .data = 8},
};
foo.call(9);
} |
I'm facing a very similar issue with dependency loops with regard to function pointers, although I'm not sure it's the exact same (tested in 0.13 and 0.12.1): const std = @import("std");
const A = struct {
field: std.meta.Tuple(&.{ i32, B }),
};
const B = union(enum) {
thing: *const fn (a: *A) void,
};
pub fn main() void {
const b: B = undefined;
_ = b;
} Weirdly enough, the dependency loop error does not occur when using an ordinary struct instead |
the recent changes to tuples (suspected cause) now make the following code error (tested on test {
_ = Foo;
}
const Foo = struct {
// ^~~~~~
// error: struct 'main.Foo' depends on itself
field: *struct { Foo },
}; the code compiles properly on |
I've encountered a similar issue with const std = @import("std");
const Node = struct {
child: ?*NodeList,
};
const NodeList = std.ArrayListAligned(Node, @alignOf(Node));
pub fn main() void {
var test_node = Node{
.child = null,
};
test_node = test_node;
} fails to compile with example.zig:3:14: error: struct 'example.Node' depends on itself It works fine when I replace The error occurs with every version of Zig I've tested, so I'm not sure if I'm just doing it wrong. |
Another example. I've been struggling with dependency loops forever, and here is the most recent: const execute = struct {
const ThreadedFn = packed struct {
f: Fn,
const Fn = *const fn (
process: *Process,
) void;
};
};
const Process = struct {
m: [@sizeOf(P)]u8,
const P = extern struct {
h: Fields,
const Fields = extern struct {
debugFn: execute.ThreadedFn,
};
};
};
fn f(_: *Process) void {}
test "die" {
const tfn = execute.ThreadedFn{.f = &f};
var p: Process = undefined;
tfn.f(&p);
} The |
Should be fixed by implementing lazy pointer types, lazy array types, or both.
The text was updated successfully, but these errors were encountered: