pub const x = 100;
pub const y = 101;
pub fn G() type {
return struct {
pub const y = 201;
pub fn f() void {
_ = x // `x` found in the outer scope
_ = @This().y; // `y` from inner scope
// how do i access `y` from the outer scope ???
}
};
}
how do i access y (= 101) defined in the outer scope from within member function f() ???
my actual use-case calls a comptime function within the anonymous inner struct, which then tries to locate some decl y found in some lexical scope starting with @This()…
said another way, can i obtain a “slice” of nested scopes which i could then query with @hasDecl() ???
how do i access y (= 101) defined in the outer scope from within member function f()???
Zig only allows shadowing when the shadowed variable can be accessed by a namespace lookup, i.e. it is a container-level declaration (meaning, within a struct/union/enum/opaque declaration). Since files are implicitly structs (if you didn’t know this: files are structs! You can put fields at top-level if you’d like!), this applies to top-level declarations. So, you need to do a namespace lookup on that struct, which, as indicated by the above commenter, you can use @This() for.
can i obtain a “slice” of nested scopes which i could then query with @hasDecl()???
No, there’s no way to programmatically get a list of scopes like that.
In general, I’d encourage avoiding shadowing even in this case where Zig permits it: it’s rarely a good idea. Not never, but rarely.
this is obviously a contrived example… but is there a way to programmatically access x (not being shadowed) given the container @This() referring to the inner scope???
No, there isn’t a programmatic way to go from a container type to its “parent” (in the sense of “syntactically enclosing”) container type, which would be necessary to access its x.
EDIT: wait, did you mean accessing the innerx (the one within f)? Either way, the answer is still no: x is declared within a function, which means you can’t access it through a namespace lookup whatsoever! It can only be referenced directly by name, and so shadowing it in any way would be a compile error. The @This() within f isn’t referring to f itself or some scope within it: it’s just the struct we’re within. @Type() returns the innermost syntactically enclosing container type.
there is only one x – defined in the outermost scope… there is no problem referring to this declaration as simply x within the method f of my inner struct…
Ah, yep, sorry, misread the code! You’re correct that @field(@This(), "x") won’t work from within f (or anywhere in the struct).
given that the compile CAN find x, shouldn’t there be a “scope searching” variant of @field?
Namespaces and scopes are somewhat distinct concepts in Zig. Scope lookups consider local variables, and do not consider usingnamespace; namespace lookups do the opposite. As a similar restriction, scope lookups consider syntactic parents, whereas namespace lookups do not. There’s not really much reason to change this: it would just complicate the language.
It’s worth remembering that these lookups are exactly what you’re doing when you write code like std.foo.bar; taking the struct type std (which happens to have no fields, so we’re using it solely as a namespace), accessing its foo declaration, and accessing that struct’s bar declaration. Expanding these lookups to consider syntactic parents would have some very strange implications regarding namespacing.