Ran into this issue in a bigger project and minified as much as I could to the following 3 files:
lib.zig
const a = @import("./a.zig");
const b = @import("./b.zig");
const ab = struct {
usingnamespace @import("./a.zig");
usingnamespace @import("./b.zig");
};
test "" {
@import("std").testing.refAllDecls(@This());
}
a.zig and b.zig (the same):
usingnamespace struct {
pub const FOO = 0;
};
$ zig test lib.zig
./lib.zig:5:5: error: import of 'FOO' overrides existing definition
usingnamespace @import("./b.zig");
^
./a.zig:2:9: note: previous definition here
pub const FOO = 0;
^
./b.zig:2:9: note: imported definition here
pub const FOO = 0;
^
So the issue here is that the FOO symbol in both a.zig and b.zig should be private to the file (note: even though it is marked pub, it is only public from the struct, which is private to the file, it would require pub usingnamespace to make it public outside the file). So there should be no conflict in lib.zig where we declare usingnamespace on both modules. In fact, if you replace those files with const FOO = 0; then no conflict occurs, but, this should be equivalent to usingnamespace struct { pub const FOO = 0; };.
Note that the error goes away if you:
FOO definition in separate files (i.e. if you copy/paste the contents of a.zig and b.zig into lib.zig)const ab definition to appear first in lib.zig, before importing the other fileslib.zig...but these lines should have no affect on the error on line 5.So the issue here is that the FOO symbol ... should be private
but yet it's defined as pub const FOO = 0;. the pub here making it not private.
expanded, this is what you're trying to compile:
const a = struct {
pub const FOO = 0;
};
const b = struct {
pub const FOO = 0;
};
const ab = struct {
pub const FOO = 0;
pub const FOO = 0;
};
...
hence the name conflict.
the pub here making it not private
The usingnamespace in a.zig and b.zig is not pub usingnamespace, so they take all the pub symbols in the target and make them non-pub symbols in the outer namespace. No pub symbols are defined in the outer namespace. The expanded form is
const a = struct {
};
const b = struct {
};
const ab = struct {
};
@nektro I had a feeling someone was going to make this mistake, In my post I tried to make it clear this wasn't the case but it looks like I failed. @SpexGuy is correct, you need to have pub usingnamespace to make the symbols you are importing public outside your own scope.
// FOO is not visible outside this file becuse we don't have `pub` on the `usingnamespace`
usingnamespace struct {
pub const FOO = 0;
};
// This is how you would make FOO public outside this file
pub usingnamespace struct {
pub const FOO = 0;
};
gotcha, my bad
@LemonBoy yes that looks like the same issue
Most helpful comment
The
usingnamespacein a.zig and b.zig is notpub usingnamespace, so they take all the pub symbols in the target and make them non-pub symbols in the outer namespace. No pub symbols are defined in the outer namespace. The expanded form is