zig
zig copied to clipboard
Function not visible inside itself through generic struct with usingnamespace
I apologize in advance for the title of this issue.
Zig Version
0.12.0-dev.1396+f6de3ec96
Steps to Reproduce and Observed Behavior
- Create a file
bug.zig:
const B = struct {
pub fn func() void {
@compileLog(@typeInfo(C).Struct.decls); // .{ .{ .name = "func" } }
@compileLog(@hasDecl(C, "func")); // false
_ = C.func; // ERROR: no member named func
}
};
fn A(comptime T: type) type {
return struct {
pub usingnamespace T;
};
}
const C = A(B);
pub fn main() !void {
C.func();
}
zig run bug.zig
bug.zig:5:14: error: struct 'bug.A(bug.B)' has no member named 'func'
_ = C.func; // ERROR: no member named func
~^~~~~
bug.zig:10:12: note: struct declared here
return struct {
^~~~~~
referenced by:
main: bug.zig:18:6
callMain: /home/lordmzte/.local/share/zupper/installs/master/lib/std/start.zig:581:32
remaining reference traces hidden; use '-freference-trace' to see all reference traces
Compile Log Output:
@as([]const builtin.Type.Declaration, .{ .{.name = "func"} })
@as(bool, false)
According to @typeInfo, the declaration func is present within C, but according to @hasDecl, it is not. Schrödinger's declaration!
Expected Behavior
The code compiles.
Equivalent to
const B = struct {
pub fn func() void {
@compileLog(@typeInfo(C).Struct.decls); // .{ .{ .name = "func" } }
@compileLog(@hasDecl(C, "func")); // false
_ = C.func; // ERROR: no member named func
}
};
const C = struct {
pub usingnamespace B;
};
pub fn main() !void {
C.func();
}
Is the circular dependency supposed to be allowed here?
Dependency loops only happen when analyzing a declaration depends on the declaration already being analyzed. A function referencing itself does not require it to be analyzed.
export fn foo() void {
foo();
}
Also encountered this issue on both 0.12.0 and 0.13.0-dev.46+3648d7df1, maybe a simpler reproduction:
const std = @import("std");
pub const Example = struct {
usingnamespace struct {}; // works without this line
pub fn foo() void {
_ = Example.foo; // error: struct 'main.Example' has no member named 'foo'
}
};
pub fn main() !void {
Example.foo();
}