-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Description
According to @andrewrk, the following should work:
const std = @import("std");
pub usingnamespace struct {
pub const FOO = 0;
};
const FOO = 1;
test {
std.debug.assert(FOO == 1);
}But currently it causes a compilation error.
Relevant IRC discussion:
<andrewrk> when resolving names, it chases pub usingnamespace decls and will find the correct name, and won't report an error on a private match
...
<marler8997> you're saying this should work? pub usingnamespace struct { pub const FOO = 0; } const FOO = @This().FOO; ??
...
<andrewrk> marler8997, yes
Original Proposal before I realized this was just a bug (you can ignore)
With the new usingnamespace semantics, symbols are only added to the "namespace" and are excluded from the "scope".
This has caused a bit of an issue with how zigwin32 handles architecture-specific symbols. zigwin32 leverages usingnamespace switch (arch) { ... } in order to limit type definitions to specific architectures. The problem is that with the new usingnamespace semantics, this prevents those symbols from being accessed within the module without having to qualify them. For my latest notes on this see https://gist.github.com/marler8997/76cfbe5958455d2e3b9d40350b90d309 I could enhance zigwin32 to detect when symbols fall into this case and then qualify all references to them, but this would add alot of noise to the bindings and make them harder to read.
The idea I had to fix this was to include a local scope definition as well, i.e.
// arch-specific definition
pub usingnamespace (arch) {
.arm => struct {
pub const FOO = 0;
}
}
// local scope introduction
const FOO = @This().FOO;The problem here is that the const FOO = @This().FOO; does not just introduce FOO into the scope, but also the namespace, which means it overrides the namespace definition causing a compilation error. This made me realize that with the new usingnamespace semantics, once a symbol is introduced into the namespace without being included into the scope, "there's no way to introduce that same symbol into the scope". That symbol is now lost to the module with no way of including it into the scope.
The other realization I have is that if Zig did have a way to introduce identifiers into the scope even once they are in the namespace, it's probably a bad idea to redefine that local scope identifier as something different than the corresponding namespace definition. So it seems to me that if we want to solve this, then what we want is a way to explicitly include namespace symbols into the local scope.
This could be done with a builtin like this:
pub usingnamespace struct {
pub const FOO = 0;
};
@includeNamespaceSymbol(FOO);One way to think about this is that if a module includes @includeNamespaceSymbol(X), then anywhere that X appears in the file, it will be considered equivalent to @This().X.
EDIT:
I wanted to add that the lack of this feature feels like a "weird asymmetry" if you consider this example.
pub usingnamespace struct {
pub const FOO = 0;
};
test {
_ = FOO; // there's no way to make this work inside this module
}But if I import that module in another module, I can define FOO and use it unqualified throughout that module:
const FOO = @import("the-previous-module.zig").FOO;
test {
_ = FOO; // now this will work
}