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
allow declaration shadowing but disallow ambiguous identifier references #678
Comments
Proposal to fix this: Name shadowing is allowed in certain special cases (see list below). When a name is declared that shadows another name, then referring to that name unqualified is a compile error. So for your example, both ways of writing the code would be equivalent, but in either case, you cannot refer to the unqualified name List of cases where shadowing is allowed:
There may be more cases to add to the list as well, but we want to keep this list as short as possible. See #683. |
This is related to the issue of being unable to create a method named after a builtin type. e.g.
fails with
One potential solution is to allow the definition, but once there is a conflict: enforce that all accesses go via a qualified scope e.g. A different solution might be along the lines of #705 (comment) |
Here is another simple example, without functions, just with nested structs:
const Foo = struct {
const Bar = struct {
name: []const u8 = "Foo Bar",
};
};
const Bar = struct {
name: []const u8 = "Just Bar",
};
pub fn main() void {
const foo_bar = Foo.Bar{};
const bar = Bar{};
} which fails with:
But this will work:
Note also that if you separate "Foo.Bar" to "foobar.zig" and "Bar" to "bar.zig", and import them, it will work as expected. How should nested structs behave? |
This comment has been minimized.
This comment has been minimized.
Notes about how this will play in relationship to
usingnamespace struct {
pub const a: i32 = 1234;
pub const b: i32 = 99;
};
usingnamespace struct {
pub const a: i32 = 5678;
};
test {
_ = a; // compile error
} If the test is replaced with only a reference to test {
_ = b; // ok
}
pub usingnamespace struct {
pub const a: i32 = 1234;
};
pub usingnamespace struct {
pub const a: i32 = 5678;
}; Even without a test, this is a compile error, because two pub declarations have the same name.
pub usingnamespace struct {
pub const a: i32 = 1234;
};
usingnamespace struct {
pub const a: i32 = 5678;
}; However a reference within the same file would be ambiguous: const This = @This();
test {
_ = This.a; // error, ambiguous reference
} Additionally, a usingnamespace decl shadowing a local decl is a compile error: usingnamespace struct {
pub const a: i32 = 5678;
};
const a: i32 = 1234; // error, name conflict |
did you mean for one of these to not be |
I really love this proposal. The use case I encountered is interface implementations, where both outer and inner structs implements the same interface: field1: i32,
field2: []const u8,
...
compound: struct {
field3: i32,
...
pub fn jsonStringify(...) !void { ... }
},
pub fn jsonStringify(...) !void {...} Without this proposal, the workaround could be define the inner struct in a separate file, which is unnecessarily clumsy. The same is true for constant declarations, they might be part of the interface too (e.g. #8987). |
This works and compiles as expected:
However, if the inner
init
is defined as apub const
, it fails:The text was updated successfully, but these errors were encountered: